summaryrefslogtreecommitdiffstats
path: root/sway/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/config.c')
-rw-r--r--sway/config.c1027
1 files changed, 153 insertions, 874 deletions
diff --git a/sway/config.c b/sway/config.c
index a33b8edc..90b833ab 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -12,17 +12,19 @@
12#include <signal.h> 12#include <signal.h>
13#include <libinput.h> 13#include <libinput.h>
14#include <limits.h> 14#include <limits.h>
15#include <float.h>
16#include <dirent.h> 15#include <dirent.h>
17#include <strings.h> 16#include <strings.h>
18#include "wayland-desktop-shell-server-protocol.h" 17#ifdef __linux__
18#include <linux/input-event-codes.h>
19#elif __FreeBSD__
20#include <dev/evdev/input-event-codes.h>
21#endif
22#include <wlr/types/wlr_output.h>
23#include "sway/input/input-manager.h"
24#include "sway/input/seat.h"
19#include "sway/commands.h" 25#include "sway/commands.h"
20#include "sway/config.h" 26#include "sway/config.h"
21#include "sway/layout.h" 27#include "sway/tree/layout.h"
22#include "sway/input_state.h"
23#include "sway/criteria.h"
24#include "sway/input.h"
25#include "sway/border.h"
26#include "readline.h" 28#include "readline.h"
27#include "stringop.h" 29#include "stringop.h"
28#include "list.h" 30#include "list.h"
@@ -30,269 +32,102 @@
30 32
31struct sway_config *config = NULL; 33struct sway_config *config = NULL;
32 34
33static void terminate_swaybar(pid_t pid);
34
35static void free_variable(struct sway_variable *var) {
36 if (!var) {
37 return;
38 }
39 free(var->name);
40 free(var->value);
41 free(var);
42}
43
44static void free_binding(struct sway_binding *bind) {
45 if (!bind) {
46 return;
47 }
48 free_flat_list(bind->keys);
49 free(bind->command);
50 free(bind);
51}
52
53static void free_mode(struct sway_mode *mode) { 35static void free_mode(struct sway_mode *mode) {
54 if (!mode) {
55 return;
56 }
57 free(mode->name);
58 int i;
59 for (i = 0; mode->bindings && i < mode->bindings->length; ++i) {
60 free_binding(mode->bindings->items[i]);
61 }
62 list_free(mode->bindings);
63 free(mode);
64}
65
66static void free_bar(struct bar_config *bar) {
67 if (!bar) {
68 return;
69 }
70 free(bar->mode);
71 free(bar->hidden_state);
72#ifdef ENABLE_TRAY
73 free(bar->tray_output);
74 free(bar->icon_theme);
75#endif
76 free(bar->status_command);
77 free(bar->font);
78 free(bar->separator_symbol);
79 int i; 36 int i;
80 for (i = 0; bar->bindings && i < bar->bindings->length; ++i) {
81 free_sway_mouse_binding(bar->bindings->items[i]);
82 }
83 list_free(bar->bindings);
84
85 if (bar->outputs) {
86 free_flat_list(bar->outputs);
87 }
88
89 if (bar->pid != 0) {
90 terminate_swaybar(bar->pid);
91 }
92
93 free(bar->colors.background);
94 free(bar->colors.statusline);
95 free(bar->colors.separator);
96 free(bar->colors.focused_background);
97 free(bar->colors.focused_statusline);
98 free(bar->colors.focused_separator);
99 free(bar->colors.focused_workspace_border);
100 free(bar->colors.focused_workspace_bg);
101 free(bar->colors.focused_workspace_text);
102 free(bar->colors.active_workspace_border);
103 free(bar->colors.active_workspace_bg);
104 free(bar->colors.active_workspace_text);
105 free(bar->colors.inactive_workspace_border);
106 free(bar->colors.inactive_workspace_bg);
107 free(bar->colors.inactive_workspace_text);
108 free(bar->colors.urgent_workspace_border);
109 free(bar->colors.urgent_workspace_bg);
110 free(bar->colors.urgent_workspace_text);
111 free(bar->colors.binding_mode_border);
112 free(bar->colors.binding_mode_bg);
113 free(bar->colors.binding_mode_text);
114
115 free(bar);
116}
117 37
118void free_input_config(struct input_config *ic) { 38 if (!mode) {
119 if (!ic) {
120 return;
121 }
122 free(ic->identifier);
123 free(ic);
124}
125
126void free_output_config(struct output_config *oc) {
127 if (!oc) {
128 return;
129 }
130 free(oc->name);
131 free(oc->background);
132 free(oc->background_option);
133 free(oc);
134}
135
136static void free_workspace_output(struct workspace_output *wo) {
137 if (!wo) {
138 return; 39 return;
139 } 40 }
140 free(wo->output); 41 free(mode->name);
141 free(wo->workspace); 42 if (mode->keysym_bindings) {
142 free(wo); 43 for (i = 0; i < mode->keysym_bindings->length; i++) {
143} 44 free_sway_binding(mode->keysym_bindings->items[i]);
144
145static void pid_workspace_cleanup() {
146 struct timespec ts;
147 struct pid_workspace *pw = NULL;
148
149 clock_gettime(CLOCK_MONOTONIC, &ts);
150
151 // work backwards through list and remove any entries
152 // older than PID_WORKSPACE_TIMEOUT
153 for (int i = config->pid_workspaces->length - 1; i > -1; i--) {
154 pw = config->pid_workspaces->items[i];
155
156 if (difftime(ts.tv_sec, *pw->time_added) >= PID_WORKSPACE_TIMEOUT) {
157 free_pid_workspace(config->pid_workspaces->items[i]);
158 list_del(config->pid_workspaces, i);
159 } 45 }
46 list_free(mode->keysym_bindings);
160 } 47 }
161} 48 if (mode->keycode_bindings) {
162 49 for (i = 0; i < mode->keycode_bindings->length; i++) {
163// de-dupe pid_workspaces to ensure pid uniqueness 50 free_sway_binding(mode->keycode_bindings->items[i]);
164void pid_workspace_add(struct pid_workspace *pw) {
165 struct pid_workspace *list_pw = NULL;
166 struct timespec ts;
167 time_t *now = malloc(sizeof(time_t));
168 if (!now) {
169 sway_log(L_ERROR, "Allocating time for pid_workspace failed");
170 return;
171 }
172
173 pid_workspace_cleanup();
174
175 // add current time to pw
176 clock_gettime(CLOCK_MONOTONIC, &ts);
177 *now = ts.tv_sec;
178
179 pw->time_added = now;
180
181 // work backwards through list and delete any entries that
182 // have the same pid as that in our new pid_workspace
183 for (int i = config->pid_workspaces->length - 1; i > -1; i--) {
184 list_pw = config->pid_workspaces->items[i];
185
186 if (pw->pid == list_pw->pid) {
187 free_pid_workspace(config->pid_workspaces->items[i]);
188 list_del(config->pid_workspaces, i);
189 } 51 }
52 list_free(mode->keycode_bindings);
190 } 53 }
191 54 free(mode);
192 list_add(config->pid_workspaces, pw);
193}
194
195void free_pid_workspace(struct pid_workspace *pw) {
196 if (!pw) {
197 return;
198 }
199 free(pw->pid);
200 free(pw->workspace);
201 free(pw->time_added);
202 free(pw);
203}
204
205void free_command_policy(struct command_policy *policy) {
206 if (!policy) {
207 return;
208 }
209 free(policy->command);
210 free(policy);
211}
212
213void free_feature_policy(struct feature_policy *policy) {
214 if (!policy) {
215 return;
216 }
217 free(policy->program);
218 free(policy);
219} 55}
220 56
221void free_config(struct sway_config *config) { 57void free_config(struct sway_config *config) {
58 config_clear_handler_context(config);
59
222 if (!config) { 60 if (!config) {
223 return; 61 return;
224 } 62 }
225 int i;
226 for (i = 0; config->symbols && i < config->symbols->length; ++i) {
227 free_variable(config->symbols->items[i]);
228 }
229 list_free(config->symbols);
230 63
231 for (i = 0; config->modes && i < config->modes->length; ++i) { 64 // TODO: handle all currently unhandled lists as we add implementations
232 free_mode(config->modes->items[i]); 65 if (config->symbols) {
66 for (int i = 0; i < config->symbols->length; ++i) {
67 free_sway_variable(config->symbols->items[i]);
68 }
69 list_free(config->symbols);
233 } 70 }
234 list_free(config->modes); 71 if (config->modes) {
235 72 for (int i = 0; i < config->modes->length; ++i) {
236 for (i = 0; config->bars && i < config->bars->length; ++i) { 73 free_mode(config->modes->items[i]);
237 free_bar(config->bars->items[i]); 74 }
75 list_free(config->modes);
238 } 76 }
239 list_free(config->bars); 77 if (config->bars) {
240 78 for (int i = 0; i < config->bars->length; ++i) {
241 free_flat_list(config->cmd_queue); 79 free_bar_config(config->bars->items[i]);
242 80 }
243 for (i = 0; config->workspace_outputs && i < config->workspace_outputs->length; ++i) { 81 list_free(config->bars);
244 free_workspace_output(config->workspace_outputs->items[i]);
245 } 82 }
83 list_free(config->cmd_queue);
246 list_free(config->workspace_outputs); 84 list_free(config->workspace_outputs);
247
248 for (i = 0; config->pid_workspaces && i < config->pid_workspaces->length; ++i) {
249 free_pid_workspace(config->pid_workspaces->items[i]);
250 }
251 list_free(config->pid_workspaces); 85 list_free(config->pid_workspaces);
252 86 list_free(config->output_configs);
253 for (i = 0; config->criteria && i < config->criteria->length; ++i) { 87 if (config->input_configs) {
254 free_criteria(config->criteria->items[i]); 88 for (int i = 0; i < config->input_configs->length; i++) {
89 free_input_config(config->input_configs->items[i]);
90 }
91 list_free(config->input_configs);
255 } 92 }
256 list_free(config->criteria); 93 if (config->seat_configs) {
257 94 for (int i = 0; i < config->seat_configs->length; i++) {
258 for (i = 0; config->no_focus && i < config->no_focus->length; ++i) { 95 free_seat_config(config->seat_configs->items[i]);
259 free_criteria(config->no_focus->items[i]); 96 }
97 list_free(config->seat_configs);
260 } 98 }
99 list_free(config->criteria);
261 list_free(config->no_focus); 100 list_free(config->no_focus);
262 101 list_free(config->active_bar_modifiers);
263 for (i = 0; config->input_configs && i < config->input_configs->length; ++i) { 102 list_free(config->config_chain);
264 free_input_config(config->input_configs->items[i]);
265 }
266 list_free(config->input_configs);
267
268 for (i = 0; config->output_configs && i < config->output_configs->length; ++i) {
269 free_output_config(config->output_configs->items[i]);
270 }
271 list_free(config->output_configs);
272
273 for (i = 0; config->command_policies && i < config->command_policies->length; ++i) {
274 free_command_policy(config->command_policies->items[i]);
275 }
276 list_free(config->command_policies); 103 list_free(config->command_policies);
277
278 for (i = 0; config->feature_policies && i < config->feature_policies->length; ++i) {
279 free_feature_policy(config->feature_policies->items[i]);
280 }
281 list_free(config->feature_policies); 104 list_free(config->feature_policies);
282 105 list_free(config->ipc_policies);
283 list_free(config->active_bar_modifiers); 106 free(config->current_bar);
284 free_flat_list(config->config_chain);
285 free(config->font);
286 free(config->floating_scroll_up_cmd); 107 free(config->floating_scroll_up_cmd);
287 free(config->floating_scroll_down_cmd); 108 free(config->floating_scroll_down_cmd);
288 free(config->floating_scroll_left_cmd); 109 free(config->floating_scroll_left_cmd);
289 free(config->floating_scroll_right_cmd); 110 free(config->floating_scroll_right_cmd);
111 free(config->font);
112 free((char *)config->current_config);
290 free(config); 113 free(config);
291} 114}
292 115
293 116static void destroy_removed_seats(struct sway_config *old_config,
294static bool file_exists(const char *path) { 117 struct sway_config *new_config) {
295 return path && access(path, R_OK) != -1; 118 struct seat_config *seat_config;
119 struct sway_seat *seat;
120 int i;
121 for (i = 0; i < old_config->seat_configs->length; i++) {
122 seat_config = old_config->seat_configs->items[i];
123 /* Also destroy seats that aren't present in new config */
124 if (new_config && list_seq_find(new_config->seat_configs,
125 seat_name_cmp, seat_config->name) < 0) {
126 seat = input_manager_get_seat(input_manager,
127 seat_config->name);
128 seat_destroy(seat);
129 }
130 }
296} 131}
297 132
298static void config_defaults(struct sway_config *config) { 133static void config_defaults(struct sway_config *config) {
@@ -304,19 +139,22 @@ static void config_defaults(struct sway_config *config) {
304 if (!(config->criteria = create_list())) goto cleanup; 139 if (!(config->criteria = create_list())) goto cleanup;
305 if (!(config->no_focus = create_list())) goto cleanup; 140 if (!(config->no_focus = create_list())) goto cleanup;
306 if (!(config->input_configs = create_list())) goto cleanup; 141 if (!(config->input_configs = create_list())) goto cleanup;
142 if (!(config->seat_configs = create_list())) goto cleanup;
307 if (!(config->output_configs = create_list())) goto cleanup; 143 if (!(config->output_configs = create_list())) goto cleanup;
308 144
309 if (!(config->cmd_queue = create_list())) goto cleanup; 145 if (!(config->cmd_queue = create_list())) goto cleanup;
310 146
311 if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) goto cleanup; 147 if (!(config->current_mode = malloc(sizeof(struct sway_mode))))
148 goto cleanup;
312 if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; 149 if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup;
313 strcpy(config->current_mode->name, "default"); 150 strcpy(config->current_mode->name, "default");
314 if (!(config->current_mode->bindings = create_list())) goto cleanup; 151 if (!(config->current_mode->keysym_bindings = create_list())) goto cleanup;
152 if (!(config->current_mode->keycode_bindings = create_list())) goto cleanup;
315 list_add(config->modes, config->current_mode); 153 list_add(config->modes, config->current_mode);
316 154
317 config->floating_mod = 0; 155 config->floating_mod = 0;
318 config->dragging_key = M_LEFT_CLICK; 156 config->dragging_key = BTN_LEFT;
319 config->resizing_key = M_RIGHT_CLICK; 157 config->resizing_key = BTN_RIGHT;
320 if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup; 158 if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup;
321 if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup; 159 if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup;
322 if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup; 160 if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup;
@@ -324,7 +162,8 @@ static void config_defaults(struct sway_config *config) {
324 config->default_layout = L_NONE; 162 config->default_layout = L_NONE;
325 config->default_orientation = L_NONE; 163 config->default_orientation = L_NONE;
326 if (!(config->font = strdup("monospace 10"))) goto cleanup; 164 if (!(config->font = strdup("monospace 10"))) goto cleanup;
327 config->font_height = get_font_text_height(config->font); 165 // TODO: border
166 //config->font_height = get_font_text_height(config->font);
328 167
329 // floating view 168 // floating view
330 config->floating_maximum_width = 0; 169 config->floating_maximum_width = 0;
@@ -339,7 +178,6 @@ static void config_defaults(struct sway_config *config) {
339 config->active = false; 178 config->active = false;
340 config->failed = false; 179 config->failed = false;
341 config->auto_back_and_forth = false; 180 config->auto_back_and_forth = false;
342 config->seamless_mouse = true;
343 config->reading = false; 181 config->reading = false;
344 config->show_marks = true; 182 config->show_marks = true;
345 183
@@ -403,29 +241,8 @@ cleanup:
403 sway_abort("Unable to allocate config structures"); 241 sway_abort("Unable to allocate config structures");
404} 242}
405 243
406static int compare_modifiers(const void *left, const void *right) { 244static bool file_exists(const char *path) {
407 uint32_t a = *(uint32_t *)left; 245 return path && access(path, R_OK) != -1;
408 uint32_t b = *(uint32_t *)right;
409
410 return a - b;
411}
412
413void update_active_bar_modifiers() {
414 if (config->active_bar_modifiers->length > 0) {
415 list_free(config->active_bar_modifiers);
416 config->active_bar_modifiers = create_list();
417 }
418
419 struct bar_config *bar;
420 int i;
421 for (i = 0; i < config->bars->length; ++i) {
422 bar = config->bars->items[i];
423 if (strcmp(bar->mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) {
424 if (list_seq_find(config->active_bar_modifiers, compare_modifiers, &bar->modifier) < 0) {
425 list_add(config->active_bar_modifiers, &bar->modifier);
426 }
427 }
428 }
429} 246}
430 247
431static char *get_config_path(void) { 248static char *get_config_path(void) {
@@ -442,12 +259,12 @@ static char *get_config_path(void) {
442 char *home = getenv("HOME"); 259 char *home = getenv("HOME");
443 char *config_home = malloc(strlen(home) + strlen("/.config") + 1); 260 char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
444 if (!config_home) { 261 if (!config_home) {
445 sway_log(L_ERROR, "Unable to allocate $HOME/.config"); 262 wlr_log(L_ERROR, "Unable to allocate $HOME/.config");
446 } else { 263 } else {
447 strcpy(config_home, home); 264 strcpy(config_home, home);
448 strcat(config_home, "/.config"); 265 strcat(config_home, "/.config");
449 setenv("XDG_CONFIG_HOME", config_home, 1); 266 setenv("XDG_CONFIG_HOME", config_home, 1);
450 sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); 267 wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
451 free(config_home); 268 free(config_home);
452 } 269 }
453 } 270 }
@@ -463,6 +280,7 @@ static char *get_config_path(void) {
463 if (file_exists(path)) { 280 if (file_exists(path)) {
464 return path; 281 return path;
465 } 282 }
283 free(path);
466 } 284 }
467 } 285 }
468 286
@@ -472,7 +290,7 @@ static char *get_config_path(void) {
472const char *current_config_path; 290const char *current_config_path;
473 291
474static bool load_config(const char *path, struct sway_config *config) { 292static bool load_config(const char *path, struct sway_config *config) {
475 sway_log(L_INFO, "Loading config from %s", path); 293 wlr_log(L_INFO, "Loading config from %s", path);
476 current_config_path = path; 294 current_config_path = path;
477 295
478 struct stat sb; 296 struct stat sb;
@@ -481,13 +299,13 @@ static bool load_config(const char *path, struct sway_config *config) {
481 } 299 }
482 300
483 if (path == NULL) { 301 if (path == NULL) {
484 sway_log(L_ERROR, "Unable to find a config file!"); 302 wlr_log(L_ERROR, "Unable to find a config file!");
485 return false; 303 return false;
486 } 304 }
487 305
488 FILE *f = fopen(path, "r"); 306 FILE *f = fopen(path, "r");
489 if (!f) { 307 if (!f) {
490 sway_log(L_ERROR, "Unable to open %s for reading", path); 308 wlr_log(L_ERROR, "Unable to open %s for reading", path);
491 return false; 309 return false;
492 } 310 }
493 311
@@ -495,20 +313,14 @@ static bool load_config(const char *path, struct sway_config *config) {
495 fclose(f); 313 fclose(f);
496 314
497 if (!config_load_success) { 315 if (!config_load_success) {
498 sway_log(L_ERROR, "Error(s) loading config!"); 316 wlr_log(L_ERROR, "Error(s) loading config!");
499 } 317 }
500 318
501 current_config_path = NULL; 319 current_config_path = NULL;
502 return true; 320 return true;
503} 321}
504 322
505static int qstrcmp(const void* a, const void* b) {
506 return strcmp(*((char**) a), *((char**) b));
507}
508
509bool load_main_config(const char *file, bool is_active) { 323bool load_main_config(const char *file, bool is_active) {
510 input_init();
511
512 char *path; 324 char *path;
513 if (file != NULL) { 325 if (file != NULL) {
514 path = strdup(file); 326 path = strdup(file);
@@ -524,7 +336,7 @@ bool load_main_config(const char *file, bool is_active) {
524 336
525 config_defaults(config); 337 config_defaults(config);
526 if (is_active) { 338 if (is_active) {
527 sway_log(L_DEBUG, "Performing configuration file reload"); 339 wlr_log(L_DEBUG, "Performing configuration file reload");
528 config->reloading = true; 340 config->reloading = true;
529 config->active = true; 341 config->active = true;
530 } 342 }
@@ -535,11 +347,14 @@ bool load_main_config(const char *file, bool is_active) {
535 config->reading = true; 347 config->reading = true;
536 348
537 // Read security configs 349 // Read security configs
350 // TODO: Security
538 bool success = true; 351 bool success = true;
352 /*
539 DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); 353 DIR *dir = opendir(SYSCONFDIR "/sway/security.d");
540 if (!dir) { 354 if (!dir) {
541 sway_log(L_ERROR, "%s does not exist, sway will have no security configuration" 355 wlr_log(L_ERROR,
542 " and will probably be broken", SYSCONFDIR "/sway/security.d"); 356 "%s does not exist, sway will have no security configuration"
357 " and will probably be broken", SYSCONFDIR "/sway/security.d");
543 } else { 358 } else {
544 list_t *secconfigs = create_list(); 359 list_t *secconfigs = create_list();
545 char *base = SYSCONFDIR "/sway/security.d/"; 360 char *base = SYSCONFDIR "/sway/security.d/";
@@ -563,8 +378,12 @@ bool load_main_config(const char *file, bool is_active) {
563 list_qsort(secconfigs, qstrcmp); 378 list_qsort(secconfigs, qstrcmp);
564 for (int i = 0; i < secconfigs->length; ++i) { 379 for (int i = 0; i < secconfigs->length; ++i) {
565 char *_path = secconfigs->items[i]; 380 char *_path = secconfigs->items[i];
566 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { 381 if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 ||
567 sway_log(L_ERROR, "Refusing to load %s - it must be owned by root and mode 644 or 444", _path); 382 (((s.st_mode & 0777) != 0644) &&
383 (s.st_mode & 0777) != 0444)) {
384 wlr_log(L_ERROR,
385 "Refusing to load %s - it must be owned by root "
386 "and mode 644 or 444", _path);
568 success = false; 387 success = false;
569 } else { 388 } else {
570 success = success && load_config(_path, config); 389 success = success && load_config(_path, config);
@@ -573,6 +392,7 @@ bool load_main_config(const char *file, bool is_active) {
573 392
574 free_flat_list(secconfigs); 393 free_flat_list(secconfigs);
575 } 394 }
395 */
576 396
577 success = success && load_config(path, config); 397 success = success && load_config(path, config);
578 398
@@ -581,18 +401,15 @@ bool load_main_config(const char *file, bool is_active) {
581 } 401 }
582 402
583 if (old_config) { 403 if (old_config) {
404 destroy_removed_seats(old_config, config);
584 free_config(old_config); 405 free_config(old_config);
585 } 406 }
586 config->reading = false; 407 config->reading = false;
587
588 if (success) {
589 update_active_bar_modifiers();
590 }
591
592 return success; 408 return success;
593} 409}
594 410
595static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { 411static bool load_include_config(const char *path, const char *parent_dir,
412 struct sway_config *config) {
596 // save parent config 413 // save parent config
597 const char *parent_config = config->current_config; 414 const char *parent_config = config->current_config;
598 415
@@ -602,7 +419,8 @@ static bool load_include_config(const char *path, const char *parent_dir, struct
602 len = len + strlen(parent_dir) + 2; 419 len = len + strlen(parent_dir) + 2;
603 full_path = malloc(len * sizeof(char)); 420 full_path = malloc(len * sizeof(char));
604 if (!full_path) { 421 if (!full_path) {
605 sway_log(L_ERROR, "Unable to allocate full path to included config"); 422 wlr_log(L_ERROR,
423 "Unable to allocate full path to included config");
606 return false; 424 return false;
607 } 425 }
608 snprintf(full_path, len, "%s/%s", parent_dir, path); 426 snprintf(full_path, len, "%s/%s", parent_dir, path);
@@ -612,7 +430,7 @@ static bool load_include_config(const char *path, const char *parent_dir, struct
612 free(full_path); 430 free(full_path);
613 431
614 if (real_path == NULL) { 432 if (real_path == NULL) {
615 sway_log(L_DEBUG, "%s not found.", path); 433 wlr_log(L_DEBUG, "%s not found.", path);
616 return false; 434 return false;
617 } 435 }
618 436
@@ -621,7 +439,9 @@ static bool load_include_config(const char *path, const char *parent_dir, struct
621 for (j = 0; j < config->config_chain->length; ++j) { 439 for (j = 0; j < config->config_chain->length; ++j) {
622 char *old_path = config->config_chain->items[j]; 440 char *old_path = config->config_chain->items[j];
623 if (strcmp(real_path, old_path) == 0) { 441 if (strcmp(real_path, old_path) == 0) {
624 sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); 442 wlr_log(L_DEBUG,
443 "%s already included once, won't be included again.",
444 real_path);
625 free(real_path); 445 free(real_path);
626 return false; 446 return false;
627 } 447 }
@@ -673,7 +493,7 @@ bool load_include_configs(const char *path, struct sway_config *config) {
673 // restore wd 493 // restore wd
674 if (chdir(wd) < 0) { 494 if (chdir(wd) < 0) {
675 free(wd); 495 free(wd);
676 sway_log(L_ERROR, "failed to restore working directory"); 496 wlr_log(L_ERROR, "failed to restore working directory");
677 return false; 497 return false;
678 } 498 }
679 499
@@ -681,13 +501,11 @@ bool load_include_configs(const char *path, struct sway_config *config) {
681 return true; 501 return true;
682} 502}
683 503
684struct cmd_results *check_security_config() { 504void config_clear_handler_context(struct sway_config *config) {
685 if (!current_config_path || strncmp(SYSCONFDIR "/sway/security.d/", current_config_path, 505 free_input_config(config->handler_context.input_config);
686 strlen(SYSCONFDIR "/sway/security.d/")) != 0) { 506 free_seat_config(config->handler_context.seat_config);
687 return cmd_results_new(CMD_INVALID, "permit", 507
688 "This command is only permitted to run from " SYSCONFDIR "/sway/security.d/*"); 508 memset(&config->handler_context, 0, sizeof(config->handler_context));
689 }
690 return NULL;
691} 509}
692 510
693bool read_config(FILE *file, struct sway_config *config) { 511bool read_config(FILE *file, struct sway_config *config) {
@@ -717,13 +535,13 @@ bool read_config(FILE *file, struct sway_config *config) {
717 switch(res->status) { 535 switch(res->status) {
718 case CMD_FAILURE: 536 case CMD_FAILURE:
719 case CMD_INVALID: 537 case CMD_INVALID:
720 sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, 538 wlr_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number,
721 res->error, config->current_config); 539 line, res->error, config->current_config);
722 success = false; 540 success = false;
723 break; 541 break;
724 542
725 case CMD_DEFER: 543 case CMD_DEFER:
726 sway_log(L_DEBUG, "Defferring command `%s'", line); 544 wlr_log(L_DEBUG, "Deferring command `%s'", line);
727 list_add(config->cmd_queue, strdup(line)); 545 list_add(config->cmd_queue, strdup(line));
728 break; 546 break;
729 547
@@ -731,7 +549,7 @@ bool read_config(FILE *file, struct sway_config *config) {
731 if (block == CMD_BLOCK_END) { 549 if (block == CMD_BLOCK_END) {
732 block = CMD_BLOCK_MODE; 550 block = CMD_BLOCK_MODE;
733 } else { 551 } else {
734 sway_log(L_ERROR, "Invalid block '%s'", line); 552 wlr_log(L_ERROR, "Invalid block '%s'", line);
735 } 553 }
736 break; 554 break;
737 555
@@ -739,7 +557,15 @@ bool read_config(FILE *file, struct sway_config *config) {
739 if (block == CMD_BLOCK_END) { 557 if (block == CMD_BLOCK_END) {
740 block = CMD_BLOCK_INPUT; 558 block = CMD_BLOCK_INPUT;
741 } else { 559 } else {
742 sway_log(L_ERROR, "Invalid block '%s'", line); 560 wlr_log(L_ERROR, "Invalid block '%s'", line);
561 }
562 break;
563
564 case CMD_BLOCK_SEAT:
565 if (block == CMD_BLOCK_END) {
566 block = CMD_BLOCK_SEAT;
567 } else {
568 wlr_log(L_ERROR, "Invalid block '%s'", line);
743 } 569 }
744 break; 570 break;
745 571
@@ -747,7 +573,7 @@ bool read_config(FILE *file, struct sway_config *config) {
747 if (block == CMD_BLOCK_END) { 573 if (block == CMD_BLOCK_END) {
748 block = CMD_BLOCK_BAR; 574 block = CMD_BLOCK_BAR;
749 } else { 575 } else {
750 sway_log(L_ERROR, "Invalid block '%s'", line); 576 wlr_log(L_ERROR, "Invalid block '%s'", line);
751 } 577 }
752 break; 578 break;
753 579
@@ -755,7 +581,7 @@ bool read_config(FILE *file, struct sway_config *config) {
755 if (block == CMD_BLOCK_BAR) { 581 if (block == CMD_BLOCK_BAR) {
756 block = CMD_BLOCK_BAR_COLORS; 582 block = CMD_BLOCK_BAR_COLORS;
757 } else { 583 } else {
758 sway_log(L_ERROR, "Invalid block '%s'", line); 584 wlr_log(L_ERROR, "Invalid block '%s'", line);
759 } 585 }
760 break; 586 break;
761 587
@@ -763,7 +589,7 @@ bool read_config(FILE *file, struct sway_config *config) {
763 if (block == CMD_BLOCK_END) { 589 if (block == CMD_BLOCK_END) {
764 block = CMD_BLOCK_COMMANDS; 590 block = CMD_BLOCK_COMMANDS;
765 } else { 591 } else {
766 sway_log(L_ERROR, "Invalid block '%s'", line); 592 wlr_log(L_ERROR, "Invalid block '%s'", line);
767 } 593 }
768 break; 594 break;
769 595
@@ -771,7 +597,7 @@ bool read_config(FILE *file, struct sway_config *config) {
771 if (block == CMD_BLOCK_END) { 597 if (block == CMD_BLOCK_END) {
772 block = CMD_BLOCK_IPC; 598 block = CMD_BLOCK_IPC;
773 } else { 599 } else {
774 sway_log(L_ERROR, "Invalid block '%s'", line); 600 wlr_log(L_ERROR, "Invalid block '%s'", line);
775 } 601 }
776 break; 602 break;
777 603
@@ -779,56 +605,61 @@ bool read_config(FILE *file, struct sway_config *config) {
779 if (block == CMD_BLOCK_IPC) { 605 if (block == CMD_BLOCK_IPC) {
780 block = CMD_BLOCK_IPC_EVENTS; 606 block = CMD_BLOCK_IPC_EVENTS;
781 } else { 607 } else {
782 sway_log(L_ERROR, "Invalid block '%s'", line); 608 wlr_log(L_ERROR, "Invalid block '%s'", line);
783 } 609 }
784 break; 610 break;
785 611
786 case CMD_BLOCK_END: 612 case CMD_BLOCK_END:
787 switch(block) { 613 switch(block) {
788 case CMD_BLOCK_MODE: 614 case CMD_BLOCK_MODE:
789 sway_log(L_DEBUG, "End of mode block"); 615 wlr_log(L_DEBUG, "End of mode block");
790 config->current_mode = config->modes->items[0]; 616 config->current_mode = config->modes->items[0];
791 block = CMD_BLOCK_END; 617 block = CMD_BLOCK_END;
792 break; 618 break;
793 619
794 case CMD_BLOCK_INPUT: 620 case CMD_BLOCK_INPUT:
795 sway_log(L_DEBUG, "End of input block"); 621 wlr_log(L_DEBUG, "End of input block");
796 current_input_config = NULL; 622 block = CMD_BLOCK_END;
623 break;
624
625 case CMD_BLOCK_SEAT:
626 wlr_log(L_DEBUG, "End of seat block");
797 block = CMD_BLOCK_END; 627 block = CMD_BLOCK_END;
798 break; 628 break;
799 629
800 case CMD_BLOCK_BAR: 630 case CMD_BLOCK_BAR:
801 sway_log(L_DEBUG, "End of bar block"); 631 wlr_log(L_DEBUG, "End of bar block");
802 config->current_bar = NULL; 632 config->current_bar = NULL;
803 block = CMD_BLOCK_END; 633 block = CMD_BLOCK_END;
804 break; 634 break;
805 635
806 case CMD_BLOCK_BAR_COLORS: 636 case CMD_BLOCK_BAR_COLORS:
807 sway_log(L_DEBUG, "End of bar colors block"); 637 wlr_log(L_DEBUG, "End of bar colors block");
808 block = CMD_BLOCK_BAR; 638 block = CMD_BLOCK_BAR;
809 break; 639 break;
810 640
811 case CMD_BLOCK_COMMANDS: 641 case CMD_BLOCK_COMMANDS:
812 sway_log(L_DEBUG, "End of commands block"); 642 wlr_log(L_DEBUG, "End of commands block");
813 block = CMD_BLOCK_END; 643 block = CMD_BLOCK_END;
814 break; 644 break;
815 645
816 case CMD_BLOCK_IPC: 646 case CMD_BLOCK_IPC:
817 sway_log(L_DEBUG, "End of IPC block"); 647 wlr_log(L_DEBUG, "End of IPC block");
818 block = CMD_BLOCK_END; 648 block = CMD_BLOCK_END;
819 break; 649 break;
820 650
821 case CMD_BLOCK_IPC_EVENTS: 651 case CMD_BLOCK_IPC_EVENTS:
822 sway_log(L_DEBUG, "End of IPC events block"); 652 wlr_log(L_DEBUG, "End of IPC events block");
823 block = CMD_BLOCK_IPC; 653 block = CMD_BLOCK_IPC;
824 break; 654 break;
825 655
826 case CMD_BLOCK_END: 656 case CMD_BLOCK_END:
827 sway_log(L_ERROR, "Unmatched }"); 657 wlr_log(L_ERROR, "Unmatched }");
828 break; 658 break;
829 659
830 default:; 660 default:;
831 } 661 }
662 config_clear_handler_context(config);
832 default:; 663 default:;
833 } 664 }
834 free(line); 665 free(line);
@@ -838,365 +669,6 @@ bool read_config(FILE *file, struct sway_config *config) {
838 return success; 669 return success;
839} 670}
840 671
841int input_identifier_cmp(const void *item, const void *data) {
842 const struct input_config *ic = item;
843 const char *identifier = data;
844 return strcmp(ic->identifier, identifier);
845}
846
847int output_name_cmp(const void *item, const void *data) {
848 const struct output_config *output = item;
849 const char *name = data;
850
851 return strcmp(output->name, name);
852}
853
854void merge_input_config(struct input_config *dst, struct input_config *src) {
855 if (src->identifier) {
856 if (dst->identifier) {
857 free(dst->identifier);
858 }
859 dst->identifier = strdup(src->identifier);
860 }
861 if (src->accel_profile != INT_MIN) {
862 dst->accel_profile = src->accel_profile;
863 }
864 if (src->click_method != INT_MIN) {
865 dst->click_method = src->click_method;
866 }
867 if (src->drag_lock != INT_MIN) {
868 dst->drag_lock = src->drag_lock;
869 }
870 if (src->dwt != INT_MIN) {
871 dst->dwt = src->dwt;
872 }
873 if (src->middle_emulation != INT_MIN) {
874 dst->middle_emulation = src->middle_emulation;
875 }
876 if (src->natural_scroll != INT_MIN) {
877 dst->natural_scroll = src->natural_scroll;
878 }
879 if (src->pointer_accel != FLT_MIN) {
880 dst->pointer_accel = src->pointer_accel;
881 }
882 if (src->scroll_method != INT_MIN) {
883 dst->scroll_method = src->scroll_method;
884 }
885 if (src->send_events != INT_MIN) {
886 dst->send_events = src->send_events;
887 }
888 if (src->tap != INT_MIN) {
889 dst->tap = src->tap;
890 }
891}
892
893void merge_output_config(struct output_config *dst, struct output_config *src) {
894 if (src->name) {
895 if (dst->name) {
896 free(dst->name);
897 }
898 dst->name = strdup(src->name);
899 }
900 if (src->enabled != -1) {
901 dst->enabled = src->enabled;
902 }
903 if (src->width != -1) {
904 dst->width = src->width;
905 }
906 if (src->height != -1) {
907 dst->height = src->height;
908 }
909 if (src->x != -1) {
910 dst->x = src->x;
911 }
912 if (src->y != -1) {
913 dst->y = src->y;
914 }
915 if (src->scale != -1) {
916 dst->scale = src->scale;
917 }
918 if (src->background) {
919 if (dst->background) {
920 free(dst->background);
921 }
922 dst->background = strdup(src->background);
923 }
924 if (src->background_option) {
925 if (dst->background_option) {
926 free(dst->background_option);
927 }
928 dst->background_option = strdup(src->background_option);
929 }
930}
931
932static void invoke_swaybar(struct bar_config *bar) {
933 // Pipe to communicate errors
934 int filedes[2];
935 if (pipe(filedes) == -1) {
936 sway_log(L_ERROR, "Pipe setup failed! Cannot fork into bar");
937 return;
938 }
939
940 bar->pid = fork();
941 if (bar->pid == 0) {
942 close(filedes[0]);
943 if (!bar->swaybar_command) {
944 char *const cmd[] = {
945 "swaybar",
946 "-b",
947 bar->id,
948 NULL,
949 };
950
951 close(filedes[1]);
952 execvp(cmd[0], cmd);
953 _exit(EXIT_SUCCESS);
954 } else {
955 // run custom swaybar
956 int len = strlen(bar->swaybar_command) + strlen(bar->id) + 5;
957 char *command = malloc(len * sizeof(char));
958 if (!command) {
959 const char msg[] = "Unable to allocate swaybar command string";
960 int len = sizeof(msg);
961 if (write(filedes[1], &len, sizeof(int))) {};
962 if (write(filedes[1], msg, len)) {};
963 close(filedes[1]);
964 _exit(EXIT_FAILURE);
965 }
966 snprintf(command, len, "%s -b %s", bar->swaybar_command, bar->id);
967
968 char *const cmd[] = {
969 "sh",
970 "-c",
971 command,
972 NULL,
973 };
974
975 close(filedes[1]);
976 execvp(cmd[0], cmd);
977 free(command);
978 _exit(EXIT_SUCCESS);
979 }
980 }
981 close(filedes[0]);
982 int len;
983 if(read(filedes[1], &len, sizeof(int)) == sizeof(int)) {
984 char *buf = malloc(len);
985 if(!buf) {
986 sway_log(L_ERROR, "Cannot allocate error string");
987 return;
988 }
989 if(read(filedes[1], buf, len)) {
990 sway_log(L_ERROR, "%s", buf);
991 }
992 free(buf);
993 }
994 close(filedes[1]);
995}
996
997static void terminate_swaybar(pid_t pid) {
998 int ret = kill(pid, SIGTERM);
999 if (ret != 0) {
1000 sway_log(L_ERROR, "Unable to terminate swaybar [pid: %d]", pid);
1001 } else {
1002 int status;
1003 waitpid(pid, &status, 0);
1004 }
1005}
1006
1007void terminate_swaybg(pid_t pid) {
1008 int ret = kill(pid, SIGTERM);
1009 if (ret != 0) {
1010 sway_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid);
1011 } else {
1012 int status;
1013 waitpid(pid, &status, 0);
1014 }
1015}
1016
1017static bool active_output(const char *name) {
1018 int i;
1019 swayc_t *cont = NULL;
1020 for (i = 0; i < root_container.children->length; ++i) {
1021 cont = root_container.children->items[i];
1022 if (cont->type == C_OUTPUT && strcasecmp(name, cont->name) == 0) {
1023 return true;
1024 }
1025 }
1026
1027 return false;
1028}
1029
1030void load_swaybars() {
1031 // Check for bars
1032 list_t *bars = create_list();
1033 struct bar_config *bar = NULL;
1034 int i;
1035 for (i = 0; i < config->bars->length; ++i) {
1036 bar = config->bars->items[i];
1037 bool apply = false;
1038 if (bar->outputs) {
1039 int j;
1040 for (j = 0; j < bar->outputs->length; ++j) {
1041 char *o = bar->outputs->items[j];
1042 if (!strcmp(o, "*") || active_output(o)) {
1043 apply = true;
1044 break;
1045 }
1046 }
1047 } else {
1048 apply = true;
1049 }
1050 if (apply) {
1051 list_add(bars, bar);
1052 }
1053 }
1054
1055 for (i = 0; i < bars->length; ++i) {
1056 bar = bars->items[i];
1057 if (bar->pid != 0) {
1058 terminate_swaybar(bar->pid);
1059 }
1060 sway_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
1061 invoke_swaybar(bar);
1062 }
1063
1064 list_free(bars);
1065}
1066
1067void apply_input_config(struct input_config *ic, struct libinput_device *dev) {
1068 if (!ic) {
1069 return;
1070 }
1071
1072 sway_log(L_DEBUG, "apply_input_config(%s)", ic->identifier);
1073
1074 if (ic->accel_profile != INT_MIN) {
1075 sway_log(L_DEBUG, "apply_input_config(%s) accel_set_profile(%d)", ic->identifier, ic->accel_profile);
1076 libinput_device_config_accel_set_profile(dev, ic->accel_profile);
1077 }
1078 if (ic->click_method != INT_MIN) {
1079 sway_log(L_DEBUG, "apply_input_config(%s) click_set_method(%d)", ic->identifier, ic->click_method);
1080 libinput_device_config_click_set_method(dev, ic->click_method);
1081 }
1082 if (ic->drag_lock != INT_MIN) {
1083 sway_log(L_DEBUG, "apply_input_config(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method);
1084 libinput_device_config_tap_set_drag_lock_enabled(dev, ic->drag_lock);
1085 }
1086 if (ic->dwt != INT_MIN) {
1087 sway_log(L_DEBUG, "apply_input_config(%s) dwt_set_enabled(%d)", ic->identifier, ic->dwt);
1088 libinput_device_config_dwt_set_enabled(dev, ic->dwt);
1089 }
1090 if (ic->left_handed != INT_MIN) {
1091 sway_log(L_DEBUG, "apply_input_config(%s) left_handed_set_enabled(%d)", ic->identifier, ic->left_handed);
1092 libinput_device_config_left_handed_set(dev, ic->left_handed);
1093 }
1094 if (ic->middle_emulation != INT_MIN) {
1095 sway_log(L_DEBUG, "apply_input_config(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation);
1096 libinput_device_config_middle_emulation_set_enabled(dev, ic->middle_emulation);
1097 }
1098 if (ic->natural_scroll != INT_MIN) {
1099 sway_log(L_DEBUG, "apply_input_config(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll);
1100 libinput_device_config_scroll_set_natural_scroll_enabled(dev, ic->natural_scroll);
1101 }
1102 if (ic->pointer_accel != FLT_MIN) {
1103 sway_log(L_DEBUG, "apply_input_config(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel);
1104 libinput_device_config_accel_set_speed(dev, ic->pointer_accel);
1105 }
1106 if (ic->scroll_method != INT_MIN) {
1107 sway_log(L_DEBUG, "apply_input_config(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method);
1108 libinput_device_config_scroll_set_method(dev, ic->scroll_method);
1109 }
1110 if (ic->send_events != INT_MIN) {
1111 sway_log(L_DEBUG, "apply_input_config(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events);
1112 libinput_device_config_send_events_set_mode(dev, ic->send_events);
1113 }
1114 if (ic->tap != INT_MIN) {
1115 sway_log(L_DEBUG, "apply_input_config(%s) tap_set_enabled(%d)", ic->identifier, ic->tap);
1116 libinput_device_config_tap_set_enabled(dev, ic->tap);
1117 }
1118}
1119
1120void apply_output_config(struct output_config *oc, swayc_t *output) {
1121 if (oc && oc->enabled == 0) {
1122 destroy_output(output);
1123 return;
1124 }
1125
1126 if (oc && oc->width > 0 && oc->height > 0) {
1127 output->width = oc->width;
1128 output->height = oc->height;
1129
1130 sway_log(L_DEBUG, "Set %s size to %ix%i (%d)", oc->name, oc->width, oc->height, oc->scale);
1131 struct wlc_size new_size = { .w = oc->width, .h = oc->height };
1132 wlc_output_set_resolution(output->handle, &new_size, (uint32_t)oc->scale);
1133 } else if (oc) {
1134 const struct wlc_size *new_size = wlc_output_get_resolution(output->handle);
1135 wlc_output_set_resolution(output->handle, new_size, (uint32_t)oc->scale);
1136 }
1137
1138 // Find position for it
1139 if (oc && oc->x != -1 && oc->y != -1) {
1140 sway_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
1141 output->x = oc->x;
1142 output->y = oc->y;
1143 } else {
1144 int x = 0;
1145 for (int i = 0; i < root_container.children->length; ++i) {
1146 swayc_t *c = root_container.children->items[i];
1147 if (c->type == C_OUTPUT) {
1148 if (c->width + c->x > x) {
1149 x = c->width + c->x;
1150 }
1151 }
1152 }
1153 output->x = x;
1154 }
1155
1156 if (!oc || !oc->background) {
1157 // Look for a * config for background
1158 int i = list_seq_find(config->output_configs, output_name_cmp, "*");
1159 if (i >= 0) {
1160 oc = config->output_configs->items[i];
1161 } else {
1162 oc = NULL;
1163 }
1164 }
1165
1166 int output_i;
1167 for (output_i = 0; output_i < root_container.children->length; ++output_i) {
1168 if (root_container.children->items[output_i] == output) {
1169 break;
1170 }
1171 }
1172
1173 if (oc && oc->background) {
1174 if (output->bg_pid != 0) {
1175 terminate_swaybg(output->bg_pid);
1176 }
1177
1178 sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background);
1179
1180 size_t bufsize = 12;
1181 char output_id[bufsize];
1182 snprintf(output_id, bufsize, "%d", output_i);
1183 output_id[bufsize-1] = 0;
1184
1185 char *const cmd[] = {
1186 "swaybg",
1187 output_id,
1188 oc->background,
1189 oc->background_option,
1190 NULL,
1191 };
1192
1193 output->bg_pid = fork();
1194 if (output->bg_pid == 0) {
1195 execvp(cmd[0], cmd);
1196 }
1197 }
1198}
1199
1200char *do_var_replacement(char *str) { 672char *do_var_replacement(char *str) {
1201 int i; 673 int i;
1202 char *find = str; 674 char *find = str;
@@ -1216,8 +688,9 @@ char *do_var_replacement(char *str) {
1216 int vvlen = strlen(var->value); 688 int vvlen = strlen(var->value);
1217 char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); 689 char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
1218 if (!newstr) { 690 if (!newstr) {
1219 sway_log(L_ERROR, 691 wlr_log(L_ERROR,
1220 "Unable to allocate replacement during variable expansion"); 692 "Unable to allocate replacement "
693 "during variable expansion");
1221 break; 694 break;
1222 } 695 }
1223 char *newptr = newstr; 696 char *newptr = newstr;
@@ -1247,197 +720,3 @@ int workspace_output_cmp_workspace(const void *a, const void *b) {
1247 const struct workspace_output *wsa = a, *wsb = b; 720 const struct workspace_output *wsa = a, *wsb = b;
1248 return lenient_strcmp(wsa->workspace, wsb->workspace); 721 return lenient_strcmp(wsa->workspace, wsb->workspace);
1249} 722}
1250
1251int sway_binding_cmp_keys(const void *a, const void *b) {
1252 const struct sway_binding *binda = a, *bindb = b;
1253
1254 // Count keys pressed for this binding. important so we check long before
1255 // short ones. for example mod+a+b before mod+a
1256 unsigned int moda = 0, modb = 0, i;
1257
1258 // Count how any modifiers are pressed
1259 for (i = 0; i < 8 * sizeof(binda->modifiers); ++i) {
1260 moda += (binda->modifiers & 1 << i) != 0;
1261 modb += (bindb->modifiers & 1 << i) != 0;
1262 }
1263 if (bindb->keys->length + modb != binda->keys->length + moda) {
1264 return (bindb->keys->length + modb) - (binda->keys->length + moda);
1265 }
1266
1267 // Otherwise compare keys
1268 if (binda->modifiers > bindb->modifiers) {
1269 return 1;
1270 } else if (binda->modifiers < bindb->modifiers) {
1271 return -1;
1272 }
1273 struct wlc_modifiers no_mods = { 0, 0 };
1274 for (int i = 0; i < binda->keys->length; i++) {
1275 xkb_keysym_t ka = *(xkb_keysym_t *)binda->keys->items[i],
1276 kb = *(xkb_keysym_t *)bindb->keys->items[i];
1277 if (binda->bindcode) {
1278 uint32_t *keycode = binda->keys->items[i];
1279 ka = wlc_keyboard_get_keysym_for_key(*keycode, &no_mods);
1280 }
1281
1282 if (bindb->bindcode) {
1283 uint32_t *keycode = bindb->keys->items[i];
1284 kb = wlc_keyboard_get_keysym_for_key(*keycode, &no_mods);
1285 }
1286
1287 if (ka > kb) {
1288 return 1;
1289 } else if (ka < kb) {
1290 return -1;
1291 }
1292 }
1293
1294 return 0;
1295}
1296
1297int sway_binding_cmp(const void *a, const void *b) {
1298 int cmp = 0;
1299 if ((cmp = sway_binding_cmp_keys(a, b)) != 0) {
1300 return cmp;
1301 }
1302 const struct sway_binding *binda = a, *bindb = b;
1303 return lenient_strcmp(binda->command, bindb->command);
1304}
1305
1306int sway_binding_cmp_qsort(const void *a, const void *b) {
1307 return sway_binding_cmp(*(void **)a, *(void **)b);
1308}
1309
1310void free_sway_binding(struct sway_binding *binding) {
1311 if (binding->keys) {
1312 for (int i = 0; i < binding->keys->length; i++) {
1313 free(binding->keys->items[i]);
1314 }
1315 list_free(binding->keys);
1316 }
1317 if (binding->command) {
1318 free(binding->command);
1319 }
1320 free(binding);
1321}
1322
1323int sway_mouse_binding_cmp_buttons(const void *a, const void *b) {
1324 const struct sway_mouse_binding *binda = a, *bindb = b;
1325 if (binda->button > bindb->button) {
1326 return 1;
1327 }
1328 if (binda->button < bindb->button) {
1329 return -1;
1330 }
1331 return 0;
1332}
1333
1334int sway_mouse_binding_cmp(const void *a, const void *b) {
1335 int cmp = 0;
1336 if ((cmp = sway_binding_cmp_keys(a, b)) != 0) {
1337 return cmp;
1338 }
1339 const struct sway_mouse_binding *binda = a, *bindb = b;
1340 return lenient_strcmp(binda->command, bindb->command);
1341}
1342
1343int sway_mouse_binding_cmp_qsort(const void *a, const void *b) {
1344 return sway_mouse_binding_cmp(*(void **)a, *(void **)b);
1345}
1346
1347void free_sway_mouse_binding(struct sway_mouse_binding *binding) {
1348 if (binding->command) {
1349 free(binding->command);
1350 }
1351 free(binding);
1352}
1353
1354struct sway_binding *sway_binding_dup(struct sway_binding *sb) {
1355 struct sway_binding *new_sb = malloc(sizeof(struct sway_binding));
1356 if (!new_sb) {
1357 return NULL;
1358 }
1359
1360 new_sb->order = sb->order;
1361 new_sb->modifiers = sb->modifiers;
1362 new_sb->command = strdup(sb->command);
1363
1364 new_sb->keys = create_list();
1365 int i;
1366 for (i = 0; i < sb->keys->length; ++i) {
1367 xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
1368 if (!key) {
1369 free_sway_binding(new_sb);
1370 return NULL;
1371 }
1372 *key = *(xkb_keysym_t *)sb->keys->items[i];
1373 list_add(new_sb->keys, key);
1374 }
1375
1376 return new_sb;
1377}
1378
1379struct bar_config *default_bar_config(void) {
1380 struct bar_config *bar = NULL;
1381 bar = malloc(sizeof(struct bar_config));
1382 if (!bar) {
1383 return NULL;
1384 }
1385 if (!(bar->mode = strdup("dock"))) goto cleanup;
1386 if (!(bar->hidden_state = strdup("hide"))) goto cleanup;
1387 bar->modifier = WLC_BIT_MOD_LOGO;
1388 bar->outputs = NULL;
1389 bar->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM;
1390 if (!(bar->bindings = create_list())) goto cleanup;
1391 if (!(bar->status_command = strdup("while :; do date +'%Y-%m-%d %l:%M:%S %p'; sleep 1; done"))) goto cleanup;
1392 bar->pango_markup = false;
1393 bar->swaybar_command = NULL;
1394 bar->font = NULL;
1395 bar->height = -1;
1396 bar->workspace_buttons = true;
1397 bar->wrap_scroll = false;
1398 bar->separator_symbol = NULL;
1399 bar->strip_workspace_numbers = false;
1400 bar->binding_mode_indicator = true;
1401#ifdef ENABLE_TRAY
1402 bar->tray_output = NULL;
1403 bar->icon_theme = NULL;
1404 bar->tray_padding = 2;
1405 bar->activate_button = 0x110; /* BTN_LEFT */
1406 bar->context_button = 0x111; /* BTN_RIGHT */
1407 bar->secondary_button = 0x112; /* BTN_MIDDLE */
1408#endif
1409 bar->verbose = false;
1410 bar->pid = 0;
1411 // set default colors
1412 if (!(bar->colors.background = strndup("#000000ff", 9))) goto cleanup;
1413 if (!(bar->colors.statusline = strndup("#ffffffff", 9))) goto cleanup;
1414 if (!(bar->colors.separator = strndup("#666666ff", 9))) goto cleanup;
1415 if (!(bar->colors.focused_workspace_border = strndup("#4c7899ff", 9))) goto cleanup;
1416 if (!(bar->colors.focused_workspace_bg = strndup("#285577ff", 9))) goto cleanup;
1417 if (!(bar->colors.focused_workspace_text = strndup("#ffffffff", 9))) goto cleanup;
1418 if (!(bar->colors.active_workspace_border = strndup("#333333ff", 9))) goto cleanup;
1419 if (!(bar->colors.active_workspace_bg = strndup("#5f676aff", 9))) goto cleanup;
1420 if (!(bar->colors.active_workspace_text = strndup("#ffffffff", 9))) goto cleanup;
1421 if (!(bar->colors.inactive_workspace_border = strndup("#333333ff", 9))) goto cleanup;
1422 if (!(bar->colors.inactive_workspace_bg = strndup("#222222ff", 9))) goto cleanup;
1423 if (!(bar->colors.inactive_workspace_text = strndup("#888888ff", 9))) goto cleanup;
1424 if (!(bar->colors.urgent_workspace_border = strndup("#2f343aff", 9))) goto cleanup;
1425 if (!(bar->colors.urgent_workspace_bg = strndup("#900000ff", 9))) goto cleanup;
1426 if (!(bar->colors.urgent_workspace_text = strndup("#ffffffff", 9))) goto cleanup;
1427 // if the following colors stay undefined, they fall back to background,
1428 // statusline, separator and urgent_workspace_*.
1429 bar->colors.focused_background = NULL;
1430 bar->colors.focused_statusline = NULL;
1431 bar->colors.focused_separator = NULL;
1432 bar->colors.binding_mode_border = NULL;
1433 bar->colors.binding_mode_bg = NULL;
1434 bar->colors.binding_mode_text = NULL;
1435
1436 list_add(config->bars, bar);
1437
1438 return bar;
1439
1440cleanup:
1441 free_bar(bar);
1442 return NULL;
1443}