diff options
Diffstat (limited to 'sway/config.c')
-rw-r--r-- | sway/config.c | 1027 |
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 | ||
31 | struct sway_config *config = NULL; | 33 | struct sway_config *config = NULL; |
32 | 34 | ||
33 | static void terminate_swaybar(pid_t pid); | ||
34 | |||
35 | static 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 | |||
44 | static 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 | |||
53 | static void free_mode(struct sway_mode *mode) { | 35 | static 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 | |||
66 | static 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 | ||
118 | void 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 | |||
126 | void 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 | |||
136 | static 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 | |||
145 | static 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]); |
164 | void 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 | |||
195 | void 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 | |||
205 | void free_command_policy(struct command_policy *policy) { | ||
206 | if (!policy) { | ||
207 | return; | ||
208 | } | ||
209 | free(policy->command); | ||
210 | free(policy); | ||
211 | } | ||
212 | |||
213 | void free_feature_policy(struct feature_policy *policy) { | ||
214 | if (!policy) { | ||
215 | return; | ||
216 | } | ||
217 | free(policy->program); | ||
218 | free(policy); | ||
219 | } | 55 | } |
220 | 56 | ||
221 | void free_config(struct sway_config *config) { | 57 | void 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 | 116 | static void destroy_removed_seats(struct sway_config *old_config, | |
294 | static 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 | ||
298 | static void config_defaults(struct sway_config *config) { | 133 | static 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 | ||
406 | static int compare_modifiers(const void *left, const void *right) { | 244 | static 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 | |||
413 | void 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 | ||
431 | static char *get_config_path(void) { | 248 | static 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) { | |||
472 | const char *current_config_path; | 290 | const char *current_config_path; |
473 | 291 | ||
474 | static bool load_config(const char *path, struct sway_config *config) { | 292 | static 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 | ||
505 | static int qstrcmp(const void* a, const void* b) { | ||
506 | return strcmp(*((char**) a), *((char**) b)); | ||
507 | } | ||
508 | |||
509 | bool load_main_config(const char *file, bool is_active) { | 323 | bool 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 | ||
595 | static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { | 411 | static 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 | ||
684 | struct cmd_results *check_security_config() { | 504 | void 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 | ||
693 | bool read_config(FILE *file, struct sway_config *config) { | 511 | bool 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 | ||
841 | int 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 | |||
847 | int 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 | |||
854 | void 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 | |||
893 | void 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 | |||
932 | static 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 | |||
997 | static 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 | |||
1007 | void 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 | |||
1017 | static 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 | |||
1030 | void 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 | |||
1067 | void 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 | |||
1120 | void 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 | |||
1200 | char *do_var_replacement(char *str) { | 672 | char *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 | |||
1251 | int 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 | |||
1297 | int 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 | |||
1306 | int sway_binding_cmp_qsort(const void *a, const void *b) { | ||
1307 | return sway_binding_cmp(*(void **)a, *(void **)b); | ||
1308 | } | ||
1309 | |||
1310 | void 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 | |||
1323 | int 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 | |||
1334 | int 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 | |||
1343 | int sway_mouse_binding_cmp_qsort(const void *a, const void *b) { | ||
1344 | return sway_mouse_binding_cmp(*(void **)a, *(void **)b); | ||
1345 | } | ||
1346 | |||
1347 | void free_sway_mouse_binding(struct sway_mouse_binding *binding) { | ||
1348 | if (binding->command) { | ||
1349 | free(binding->command); | ||
1350 | } | ||
1351 | free(binding); | ||
1352 | } | ||
1353 | |||
1354 | struct 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 | |||
1379 | struct 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 | |||
1440 | cleanup: | ||
1441 | free_bar(bar); | ||
1442 | return NULL; | ||
1443 | } | ||