From 63b4bf500020cf35cebfdce2d73f8e359ff495c2 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 9 Jul 2018 22:54:30 +0100 Subject: Update for swaywm/wlroots#1126 --- sway/config.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index 89b7d349..d0e0e432 100644 --- a/sway/config.c +++ b/sway/config.c @@ -276,12 +276,12 @@ static char *get_config_path(void) { char *home = getenv("HOME"); char *config_home = malloc(strlen(home) + strlen("/.config") + 1); if (!config_home) { - wlr_log(L_ERROR, "Unable to allocate $HOME/.config"); + wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config"); } else { strcpy(config_home, home); strcat(config_home, "/.config"); setenv("XDG_CONFIG_HOME", config_home, 1); - wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); + wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); free(config_home); } } @@ -308,11 +308,11 @@ const char *current_config_path; static bool load_config(const char *path, struct sway_config *config) { if (path == NULL) { - wlr_log(L_ERROR, "Unable to find a config file!"); + wlr_log(WLR_ERROR, "Unable to find a config file!"); return false; } - wlr_log(L_INFO, "Loading config from %s", path); + wlr_log(WLR_INFO, "Loading config from %s", path); current_config_path = path; struct stat sb; @@ -322,7 +322,7 @@ static bool load_config(const char *path, struct sway_config *config) { FILE *f = fopen(path, "r"); if (!f) { - wlr_log(L_ERROR, "Unable to open %s for reading", path); + wlr_log(WLR_ERROR, "Unable to open %s for reading", path); return false; } @@ -330,7 +330,7 @@ static bool load_config(const char *path, struct sway_config *config) { fclose(f); if (!config_load_success) { - wlr_log(L_ERROR, "Error(s) loading config!"); + wlr_log(WLR_ERROR, "Error(s) loading config!"); } current_config_path = NULL; @@ -353,7 +353,7 @@ bool load_main_config(const char *file, bool is_active) { config_defaults(config); if (is_active) { - wlr_log(L_DEBUG, "Performing configuration file reload"); + wlr_log(WLR_DEBUG, "Performing configuration file reload"); config->reloading = true; config->active = true; } @@ -369,7 +369,7 @@ bool load_main_config(const char *file, bool is_active) { /* DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); if (!dir) { - wlr_log(L_ERROR, + wlr_log(WLR_ERROR, "%s does not exist, sway will have no security configuration" " and will probably be broken", SYSCONFDIR "/sway/security.d"); } else { @@ -398,7 +398,7 @@ bool load_main_config(const char *file, bool is_active) { if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { - wlr_log(L_ERROR, + wlr_log(WLR_ERROR, "Refusing to load %s - it must be owned by root " "and mode 644 or 444", _path); success = false; @@ -436,7 +436,7 @@ static bool load_include_config(const char *path, const char *parent_dir, len = len + strlen(parent_dir) + 2; full_path = malloc(len * sizeof(char)); if (!full_path) { - wlr_log(L_ERROR, + wlr_log(WLR_ERROR, "Unable to allocate full path to included config"); return false; } @@ -449,7 +449,7 @@ static bool load_include_config(const char *path, const char *parent_dir, free(full_path); if (real_path == NULL) { - wlr_log(L_DEBUG, "%s not found.", path); + wlr_log(WLR_DEBUG, "%s not found.", path); return false; } @@ -458,7 +458,7 @@ static bool load_include_config(const char *path, const char *parent_dir, for (j = 0; j < config->config_chain->length; ++j) { char *old_path = config->config_chain->items[j]; if (strcmp(real_path, old_path) == 0) { - wlr_log(L_DEBUG, + wlr_log(WLR_DEBUG, "%s already included once, won't be included again.", real_path); free(real_path); @@ -512,7 +512,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { // restore wd if (chdir(wd) < 0) { free(wd); - wlr_log(L_ERROR, "failed to restore working directory"); + wlr_log(WLR_ERROR, "failed to restore working directory"); return false; } @@ -527,13 +527,13 @@ static int detect_brace_on_following_line(FILE *file, char *line, char *peeked = NULL; long position = 0; do { - wlr_log(L_DEBUG, "Peeking line %d", line_number + lines + 1); + wlr_log(WLR_DEBUG, "Peeking line %d", line_number + lines + 1); free(peeked); peeked = peek_line(file, lines, &position); if (peeked) { peeked = strip_whitespace(peeked); } - wlr_log(L_DEBUG, "Peeked line: `%s`", peeked); + wlr_log(WLR_DEBUG, "Peeked line: `%s`", peeked); lines++; } while (peeked && strlen(peeked) == 0); @@ -552,7 +552,7 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { + (add_brace ? 2 : 0) + 1; char *expanded = calloc(1, size); if (!expanded) { - wlr_log(L_ERROR, "Cannot allocate expanded line buffer"); + wlr_log(WLR_ERROR, "Cannot allocate expanded line buffer"); return NULL; } snprintf(expanded, size, "%s%s%s%s", block ? block : "", @@ -572,7 +572,7 @@ bool read_config(FILE *file, struct sway_config *config) { continue; } line_number++; - wlr_log(L_DEBUG, "Read line %d: %s", line_number, line); + wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); line = strip_whitespace(line); if (line[0] == '#') { free(line); @@ -586,7 +586,7 @@ bool read_config(FILE *file, struct sway_config *config) { line_number); if (brace_detected > 0) { line_number += brace_detected; - wlr_log(L_DEBUG, "Detected open brace on line %d", line_number); + wlr_log(WLR_DEBUG, "Detected open brace on line %d", line_number); } char *expanded = expand_line(block, line, brace_detected > 0); if (!expanded) { @@ -594,7 +594,7 @@ bool read_config(FILE *file, struct sway_config *config) { list_free(stack); return false; } - wlr_log(L_DEBUG, "Expanded line: %s", expanded); + wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); struct cmd_results *res; if (block && strcmp(block, "") == 0) { // Special case @@ -606,23 +606,23 @@ bool read_config(FILE *file, struct sway_config *config) { switch(res->status) { case CMD_FAILURE: case CMD_INVALID: - wlr_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, + wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, res->error, config->current_config); success = false; break; case CMD_DEFER: - wlr_log(L_DEBUG, "Deferring command `%s'", line); + wlr_log(WLR_DEBUG, "Deferring command `%s'", line); list_add(config->cmd_queue, strdup(line)); break; case CMD_BLOCK_COMMANDS: - wlr_log(L_DEBUG, "Entering commands block"); + wlr_log(WLR_DEBUG, "Entering commands block"); list_insert(stack, 0, ""); break; case CMD_BLOCK: - wlr_log(L_DEBUG, "Entering block '%s'", res->input); + wlr_log(WLR_DEBUG, "Entering block '%s'", res->input); list_insert(stack, 0, strdup(res->input)); if (strcmp(res->input, "bar") == 0) { config->current_bar = NULL; @@ -631,7 +631,7 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_BLOCK_END: if (!block) { - wlr_log(L_DEBUG, "Unmatched '}' on line %i", line_number); + wlr_log(WLR_DEBUG, "Unmatched '}' on line %i", line_number); success = false; break; } @@ -639,7 +639,7 @@ bool read_config(FILE *file, struct sway_config *config) { config->current_bar = NULL; } - wlr_log(L_DEBUG, "Exiting block '%s'", block); + wlr_log(WLR_DEBUG, "Exiting block '%s'", block); list_del(stack, 0); free(block); memset(&config->handler_context, 0, @@ -682,7 +682,7 @@ char *do_var_replacement(char *str) { int vvlen = strlen(var->value); char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); if (!newstr) { - wlr_log(L_ERROR, + wlr_log(WLR_ERROR, "Unable to allocate replacement " "during variable expansion"); break; -- cgit v1.2.3 From 23c1c26c3fedf5470dbee9fe97c2374a48588863 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 8 Jul 2018 20:34:47 +0100 Subject: Add get_config message type to ipc --- include/ipc.h | 1 + include/sway/config.h | 4 +-- sway/commands/output/background.c | 2 +- sway/commands/reload.c | 2 +- sway/config.c | 53 ++++++++++++++++++++++++++++++--------- sway/ipc-json.c | 2 ++ sway/ipc-server.c | 12 +++++++++ swaymsg/main.c | 15 ++++++++++- swaymsg/swaymsg.1.scd | 3 +++ 9 files changed, 76 insertions(+), 18 deletions(-) (limited to 'sway/config.c') diff --git a/include/ipc.h b/include/ipc.h index c9c5b1cd..6f6795b3 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -14,6 +14,7 @@ enum ipc_command_type { IPC_GET_BAR_CONFIG = 6, IPC_GET_VERSION = 7, IPC_GET_BINDING_MODES = 8, + IPC_GET_CONFIG = 9, // sway-specific command types IPC_GET_INPUTS = 100, diff --git a/include/sway/config.h b/include/sway/config.h index ac668c24..d5e4116f 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -341,6 +341,7 @@ struct sway_config { int gaps_outer; list_t *config_chain; + const char *current_config_path; const char *current_config; enum sway_container_border border; @@ -496,7 +497,4 @@ void config_update_font_height(bool recalculate); /* Global config singleton. */ extern struct sway_config *config; -/* Config file currently being read */ -extern const char *current_config_path; - #endif diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index c2c138f8..4ed56c2a 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c @@ -80,7 +80,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { if (config->reading && *src != '/') { // src file is inside configuration dir - char *conf = strdup(config->current_config); + char *conf = strdup(config->current_config_path); if (!conf) { wlr_log(WLR_ERROR, "Failed to duplicate string"); free(src); diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 9fc213c4..c6715f9c 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -7,7 +7,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) { if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { return error; } - if (!load_main_config(config->current_config, true)) { + if (!load_main_config(config->current_config_path, true)) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } diff --git a/sway/config.c b/sway/config.c index d0e0e432..c59f4f0d 100644 --- a/sway/config.c +++ b/sway/config.c @@ -117,6 +117,7 @@ void free_config(struct sway_config *config) { free(config->floating_scroll_left_cmd); free(config->floating_scroll_right_cmd); free(config->font); + free((char *)config->current_config_path); free((char *)config->current_config); free(config); } @@ -205,6 +206,7 @@ static void config_defaults(struct sway_config *config) { if (!(config->active_bar_modifiers = create_list())) goto cleanup; if (!(config->config_chain = create_list())) goto cleanup; + config->current_config_path = NULL; config->current_config = NULL; // borders @@ -304,8 +306,6 @@ static char *get_config_path(void) { return NULL; // Not reached } -const char *current_config_path; - static bool load_config(const char *path, struct sway_config *config) { if (path == NULL) { wlr_log(WLR_ERROR, "Unable to find a config file!"); @@ -313,7 +313,6 @@ static bool load_config(const char *path, struct sway_config *config) { } wlr_log(WLR_INFO, "Loading config from %s", path); - current_config_path = path; struct stat sb; if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { @@ -333,7 +332,6 @@ static bool load_config(const char *path, struct sway_config *config) { wlr_log(WLR_ERROR, "Error(s) loading config!"); } - current_config_path = NULL; return true; } @@ -358,7 +356,7 @@ bool load_main_config(const char *file, bool is_active) { config->active = true; } - config->current_config = path; + config->current_config_path = path; list_add(config->config_chain, path); config->reading = true; @@ -428,7 +426,7 @@ bool load_main_config(const char *file, bool is_active) { static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { // save parent config - const char *parent_config = config->current_config; + const char *parent_config = config->current_config_path; char *full_path; int len = strlen(path); @@ -466,25 +464,25 @@ static bool load_include_config(const char *path, const char *parent_dir, } } - config->current_config = real_path; + config->current_config_path = real_path; list_add(config->config_chain, real_path); int index = config->config_chain->length - 1; if (!load_config(real_path, config)) { free(real_path); - config->current_config = parent_config; + config->current_config_path = parent_config; list_del(config->config_chain, index); return false; } - // restore current_config - config->current_config = parent_config; + // restore current_config_path + config->current_config_path = parent_config; return true; } bool load_include_configs(const char *path, struct sway_config *config) { char *wd = getcwd(NULL, 0); - char *parent_path = strdup(config->current_config); + char *parent_path = strdup(config->current_config_path); const char *parent_dir = dirname(parent_path); if (chdir(parent_dir) < 0) { @@ -561,6 +559,23 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { } bool read_config(FILE *file, struct sway_config *config) { + bool reading_main_config = false; + char *current_config, *config_pos; + long config_size = 0; + if (config->current_config == NULL) { + reading_main_config = true; + + fseek(file, 0, SEEK_END); + config_size = ftell(file); + rewind(file); + + config_pos = current_config = malloc(config_size + 1); + if (current_config == NULL) { + wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); + return false; + } + } + bool success = true; int line_number = 0; char *line; @@ -573,6 +588,14 @@ bool read_config(FILE *file, struct sway_config *config) { } line_number++; wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); + + if (reading_main_config) { + size_t l = strlen(line); + memcpy(config_pos, line, l); // don't copy terminating character + config_pos += l; + *config_pos++ = '\n'; + } + line = strip_whitespace(line); if (line[0] == '#') { free(line); @@ -592,6 +615,8 @@ bool read_config(FILE *file, struct sway_config *config) { if (!expanded) { list_foreach(stack, free); list_free(stack); + free(line); + free(current_config); return false; } wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); @@ -607,7 +632,7 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_FAILURE: case CMD_INVALID: wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number, - line, res->error, config->current_config); + line, res->error, config->current_config_path); success = false; break; @@ -652,6 +677,10 @@ bool read_config(FILE *file, struct sway_config *config) { list_foreach(stack, free); list_free(stack); + if (reading_main_config) { + current_config[config_size - 1] = '\0'; + config->current_config = current_config; + } return success; } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index b9289e25..3d0e88f0 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -2,6 +2,7 @@ #include #include #include "log.h" +#include "sway/config.h" #include "sway/ipc-json.h" #include "sway/tree/container.h" #include "sway/tree/workspace.h" @@ -41,6 +42,7 @@ json_object *ipc_json_get_version() { json_object_object_add(version, "major", json_object_new_int(major)); json_object_object_add(version, "minor", json_object_new_int(minor)); json_object_object_add(version, "patch", json_object_new_int(patch)); + json_object_object_add(version, "loaded_config_file_name", json_object_new_string(config->current_config_path)); return version; } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 70a4141e..c5161a6b 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -17,6 +17,7 @@ #include #include #include "sway/commands.h" +#include "sway/config.h" #include "sway/ipc-json.h" #include "sway/ipc-server.h" #include "sway/output.h" @@ -681,6 +682,17 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_CONFIG: + { + json_object *json = json_object_new_object(); + json_object_object_add(json, "config", json_object_new_string(config->current_config)); + const char *json_string = json_object_to_json_string(json); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(json); // free + goto exit_cleanup; + } + default: wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; diff --git a/swaymsg/main.c b/swaymsg/main.c index 42e488f3..4c068f69 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -240,6 +240,12 @@ static void pretty_print_version(json_object *v) { printf("sway version %s\n", json_object_get_string(ver)); } +static void pretty_print_config(json_object *c) { + json_object *config; + json_object_object_get_ex(c, "config", &config); + printf("%s\n", json_object_get_string(config)); +} + static void pretty_print_clipboard(json_object *v) { if (success(v, true)) { if (json_object_is_type(v, json_type_array)) { @@ -277,7 +283,7 @@ static void pretty_print(int type, json_object *resp) { if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && type != IPC_GET_VERSION && type != IPC_GET_CLIPBOARD && - type != IPC_GET_SEATS) { + type != IPC_GET_SEATS && type != IPC_GET_CONFIG) { printf("%s\n", json_object_to_json_string_ext(resp, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); return; @@ -288,6 +294,11 @@ static void pretty_print(int type, json_object *resp) { return; } + if (type == IPC_GET_CONFIG) { + pretty_print_config(resp); + return; + } + if (type == IPC_GET_CLIPBOARD) { pretty_print_clipboard(resp); return; @@ -409,6 +420,8 @@ int main(int argc, char **argv) { type = IPC_GET_VERSION; } else if (strcasecmp(cmdtype, "get_binding_modes") == 0) { type = IPC_GET_BINDING_MODES; + } else if (strcasecmp(cmdtype, "get_config") == 0) { + type = IPC_GET_CONFIG; } else if (strcasecmp(cmdtype, "get_clipboard") == 0) { type = IPC_GET_CLIPBOARD; } else { diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index f9b600b9..59a706d4 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -62,6 +62,9 @@ _swaymsg_ [options...] [message] *get\_binding\_modes* Gets a JSON-encoded list of currently configured binding modes. +*get\_config* + Gets a JSON-encoded copy of the current configuration. + *get\_clipboard* Get JSON-encoded information about the clipboard. Returns the current clipboard mime-types if called without -- cgit v1.2.3 From fbecfc2d35b13e640167e73d62ff61c230559dad Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Thu, 12 Jul 2018 13:00:57 -0400 Subject: config.c: fix current_config uninit warning (#2249) --- sway/config.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index c59f4f0d..d2386f46 100644 --- a/sway/config.c +++ b/sway/config.c @@ -560,7 +560,7 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { bool read_config(FILE *file, struct sway_config *config) { bool reading_main_config = false; - char *current_config, *config_pos; + char *this_config = NULL, *config_pos; long config_size = 0; if (config->current_config == NULL) { reading_main_config = true; @@ -569,8 +569,8 @@ bool read_config(FILE *file, struct sway_config *config) { config_size = ftell(file); rewind(file); - config_pos = current_config = malloc(config_size + 1); - if (current_config == NULL) { + config_pos = this_config = malloc(config_size + 1); + if (this_config == NULL) { wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); return false; } @@ -616,7 +616,7 @@ bool read_config(FILE *file, struct sway_config *config) { list_foreach(stack, free); list_free(stack); free(line); - free(current_config); + free(this_config); return false; } wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); @@ -678,8 +678,8 @@ bool read_config(FILE *file, struct sway_config *config) { list_free(stack); if (reading_main_config) { - current_config[config_size - 1] = '\0'; - config->current_config = current_config; + this_config[config_size - 1] = '\0'; + config->current_config = this_config; } return success; } -- cgit v1.2.3 From 2032f85d94f2f222282b242116b3e827dd458f6c Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 14 Jul 2018 23:14:55 +1000 Subject: Simplify transactions by utilising a dirty flag on containers This PR changes the way we handle transactions to a more simple method. The new method is to mark containers as dirty from low level code (eg. arranging, or container_destroy, and eventually seat_set_focus), then call transaction_commit_dirty which picks up those containers and runs them through a transaction. The old methods of using transactions (arrange_and_commit, or creating one manually) are now no longer possible. The highest-level code (execute_command and view implementation handlers) will call transaction_commit_dirty, so most other code just needs to set containers as dirty. This is done by arranging, but can also be done by calling container_set_dirty. --- include/sway/desktop/transaction.h | 33 ++++++---------- include/sway/server.h | 5 +-- include/sway/tree/arrange.h | 22 +---------- include/sway/tree/container.h | 10 +++++ sway/commands.c | 2 + sway/commands/border.c | 2 +- sway/commands/floating.c | 2 +- sway/commands/fullscreen.c | 2 +- sway/commands/gaps.c | 8 ++-- sway/commands/layout.c | 2 +- sway/commands/move.c | 25 ++++-------- sway/commands/reload.c | 2 +- sway/commands/resize.c | 6 +-- sway/commands/smart_gaps.c | 2 +- sway/commands/split.c | 2 +- sway/commands/swap.c | 9 +---- sway/config.c | 2 +- sway/desktop/layer_shell.c | 3 +- sway/desktop/output.c | 14 ++++--- sway/desktop/transaction.c | 35 +++++++++-------- sway/desktop/xdg_shell.c | 8 ++-- sway/desktop/xdg_shell_v6.c | 8 ++-- sway/desktop/xwayland.c | 8 ++-- sway/server.c | 5 +-- sway/tree/arrange.c | 78 +++++++++++++------------------------- sway/tree/container.c | 24 ++++++------ sway/tree/layout.c | 3 +- sway/tree/view.c | 5 ++- sway/tree/workspace.c | 2 +- 29 files changed, 139 insertions(+), 190 deletions(-) (limited to 'sway/config.c') diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 7ab80eb8..cee4afed 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -6,34 +6,25 @@ /** * Transactions enable us to perform atomic layout updates. * - * When we want to make adjustments to the layout, we create a transaction. - * A transaction contains a list of affected containers and their new state. + * A transaction contains a list of containers and their new state. * A state might contain a new size, or new border settings, or new parent/child * relationships. * - * Calling transaction_commit() makes sway notify of all the affected clients - * with their new sizes. We then wait for all the views to respond with their - * new surface sizes. When all are ready, or when a timeout has passed, we apply - * the updates all at the same time. - */ - -struct sway_transaction; - -/** - * Create a new transaction. - */ -struct sway_transaction *transaction_create(void); - -/** - * Add a container's pending state to the transaction. + * Committing a transaction makes sway notify of all the affected clients with + * their new sizes. We then wait for all the views to respond with their new + * surface sizes. When all are ready, or when a timeout has passed, we apply the + * updates all at the same time. + * + * When we want to make adjustments to the layout, we change the pending state + * in containers, mark them as dirty and call transaction_commit_dirty(). This + * create and commits a transaction from the dirty containers. */ -void transaction_add_container(struct sway_transaction *transaction, - struct sway_container *container); /** - * Submit a transaction to the client views for configuration. + * Find all dirty containers, create and commit a transaction containing them, + * and unmark them as dirty. */ -void transaction_commit(struct sway_transaction *transaction); +void transaction_commit_dirty(void); /** * Notify the transaction system that a view is ready for the new layout. diff --git a/include/sway/server.h b/include/sway/server.h index a3e32898..a017d1c4 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -47,10 +47,7 @@ struct sway_server { bool debug_txn_timings; list_t *transactions; - - // When a view is being destroyed and is waiting for a transaction to - // complete it will be stored here. - list_t *destroying_containers; + list_t *dirty_containers; }; struct sway_server server; diff --git a/include/sway/tree/arrange.h b/include/sway/tree/arrange.h index 58235642..d6abcc81 100644 --- a/include/sway/tree/arrange.h +++ b/include/sway/tree/arrange.h @@ -11,26 +11,8 @@ void remove_gaps(struct sway_container *c); void add_gaps(struct sway_container *c); /** - * Arrange layout for all the children of the given container, and add them to - * the given transaction. - * - * Use this function if you need to arrange multiple sections of the tree in one - * transaction. - * - * You must set the desired state of the container before calling - * arrange_windows, then don't change any state-tracked properties in the - * container until you've called transaction_commit. + * Arrange layout for all the children of the given container. */ -void arrange_windows(struct sway_container *container, - struct sway_transaction *transaction); - -/** - * Arrange layout for the given container and commit the transaction. - * - * This function is a wrapper around arrange_windows, and handles creating and - * committing the transaction for you. Use this function if you're only doing - * one arrange operation. - */ -void arrange_and_commit(struct sway_container *container); +void arrange_windows(struct sway_container *container); #endif diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index a69da9db..11780916 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -144,6 +144,10 @@ struct sway_container { bool destroying; + // If true, indicates that the container has pending state that differs from + // the current. + bool dirty; + struct { struct wl_signal destroy; // Raised after the tree updates, but before arrange_windows @@ -303,4 +307,10 @@ void container_get_box(struct sway_container *container, struct wlr_box *box); void container_floating_move_to(struct sway_container *con, double lx, double ly); +/** + * Mark a container as dirty if it isn't already. Dirty containers will be + * included in the next transaction then unmarked as dirty. + */ +void container_set_dirty(struct sway_container *container); + #endif diff --git a/sway/commands.c b/sway/commands.c index addd64a6..50d949d4 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -9,6 +9,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/criteria.h" +#include "sway/desktop/transaction.h" #include "sway/security.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -322,6 +323,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { cleanup: free(exec); free(views); + transaction_commit_dirty(); if (!results) { results = cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/border.c b/sway/commands/border.c index 6db85395..9c19e20a 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c @@ -42,7 +42,7 @@ struct cmd_results *cmd_border(int argc, char **argv) { container_set_geometry_from_floating_view(view->swayc); } - arrange_and_commit(view->swayc); + arrange_windows(view->swayc); struct sway_seat *seat = input_manager_current_seat(input_manager); if (seat->cursor) { diff --git a/sway/commands/floating.c b/sway/commands/floating.c index e6003521..6ab56c3b 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c @@ -37,7 +37,7 @@ struct cmd_results *cmd_floating(int argc, char **argv) { container_set_floating(container, wants_floating); struct sway_container *workspace = container_parent(container, C_WORKSPACE); - arrange_and_commit(workspace); + arrange_windows(workspace); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index 1a4d8b41..0b5beaa2 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -34,7 +34,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { view_set_fullscreen(view, wants_fullscreen); struct sway_container *workspace = container_parent(container, C_WORKSPACE); - arrange_and_commit(workspace->parent); + arrange_windows(workspace->parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index 801fb179..3906eb70 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c @@ -43,7 +43,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "gaps", "gaps edge_gaps on|off|toggle"); } - arrange_and_commit(&root_container); + arrange_windows(&root_container); } else { int amount_idx = 0; // the current index in argv enum gaps_op op = GAPS_OP_SET; @@ -124,7 +124,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { if (amount_idx == 0) { // gaps config->gaps_inner = val; config->gaps_outer = val; - arrange_and_commit(&root_container); + arrange_windows(&root_container); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } // Other variants. The middle-length variant (gaps inner|outer ) @@ -155,7 +155,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { } else { config->gaps_outer = total; } - arrange_and_commit(&root_container); + arrange_windows(&root_container); } else { struct sway_container *c = config->handler_context.current_container; @@ -169,7 +169,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { c->gaps_outer = total; } - arrange_and_commit(c->parent ? c->parent : &root_container); + arrange_windows(c->parent ? c->parent : &root_container); } } diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 9945fa5c..c446f1f9 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -49,7 +49,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } container_notify_subtree_changed(parent); - arrange_and_commit(parent); + arrange_windows(parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/move.c b/sway/commands/move.c index a1c1e018..6ec050a8 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -6,7 +6,6 @@ #include #include #include "sway/commands.h" -#include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" #include "sway/output.h" @@ -105,10 +104,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, // TODO: Ideally we would arrange the surviving parent after reaping, // but container_reap_empty does not return it, so we arrange the // workspace instead. - struct sway_transaction *txn = transaction_create(); - arrange_windows(old_ws, txn); - arrange_windows(destination->parent, txn); - transaction_commit(txn); + arrange_windows(old_ws); + arrange_windows(destination->parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } else if (strcasecmp(argv[1], "to") == 0 @@ -144,10 +141,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, // TODO: Ideally we would arrange the surviving parent after reaping, // but container_reap_empty does not return it, so we arrange the // workspace instead. - struct sway_transaction *txn = transaction_create(); - arrange_windows(old_ws, txn); - arrange_windows(focus->parent, txn); - transaction_commit(txn); + arrange_windows(old_ws); + arrange_windows(focus->parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -177,10 +172,8 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, } container_move_to(current, destination); - struct sway_transaction *txn = transaction_create(); - arrange_windows(source, txn); - arrange_windows(destination, txn); - transaction_commit(txn); + arrange_windows(source); + arrange_windows(destination); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -238,12 +231,10 @@ static struct cmd_results *move_in_direction(struct sway_container *container, container_move(container, direction, move_amt); struct sway_container *new_ws = container_parent(container, C_WORKSPACE); - struct sway_transaction *txn = transaction_create(); - arrange_windows(old_ws, txn); + arrange_windows(old_ws); if (new_ws != old_ws) { - arrange_windows(new_ws, txn); + arrange_windows(new_ws); } - transaction_commit(txn); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index c6715f9c..cea6a94b 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -12,6 +12,6 @@ struct cmd_results *cmd_reload(int argc, char **argv) { } load_swaybars(); - arrange_and_commit(&root_container); + arrange_windows(&root_container); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 2cf811d8..e657864c 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -268,7 +268,7 @@ static void resize_tiled(int amount, enum resize_axis axis) { } } - arrange_and_commit(parent->parent); + arrange_windows(parent->parent); } /** @@ -338,7 +338,7 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, view->height += grow_height; } - arrange_and_commit(con); + arrange_windows(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -410,7 +410,7 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, view->height += grow_height; } - arrange_and_commit(con); + arrange_windows(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c index f687e78e..7d27e571 100644 --- a/sway/commands/smart_gaps.c +++ b/sway/commands/smart_gaps.c @@ -23,7 +23,7 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) { "Expected 'smart_gaps ' "); } - arrange_and_commit(&root_container); + arrange_windows(&root_container); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/split.c b/sway/commands/split.c index c40f4d9f..313799da 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -16,7 +16,7 @@ static struct cmd_results *do_split(int layout) { } struct sway_container *parent = container_split(con, layout); container_create_notify(parent); - arrange_and_commit(parent->parent); + arrange_windows(parent->parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/swap.c b/sway/commands/swap.c index e052058f..2fc88308 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -1,7 +1,6 @@ #include #include #include "sway/commands.h" -#include "sway/desktop/transaction.h" #include "sway/tree/arrange.h" #include "sway/tree/layout.h" #include "sway/tree/view.h" @@ -79,14 +78,10 @@ struct cmd_results *cmd_swap(int argc, char **argv) { container_swap(current, other); - struct sway_transaction *txn = transaction_create(); - arrange_windows(current->parent, txn); - + arrange_windows(current->parent); if (other->parent != current->parent) { - arrange_windows(other->parent, txn); + arrange_windows(other->parent); } - transaction_commit(txn); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config.c b/sway/config.c index d2386f46..636f5f57 100644 --- a/sway/config.c +++ b/sway/config.c @@ -773,6 +773,6 @@ void config_update_font_height(bool recalculate) { } if (config->font_height != prev_max_height) { - arrange_and_commit(&root_container); + arrange_windows(&root_container); } } diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 16910c7e..91baa6f8 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -12,7 +12,6 @@ #include "sway/layers.h" #include "sway/output.h" #include "sway/server.h" -#include "sway/tree/arrange.h" #include "sway/tree/layout.h" #include "log.h" @@ -176,7 +175,7 @@ void arrange_layers(struct sway_output *output) { sizeof(struct wlr_box)) != 0) { wlr_log(WLR_DEBUG, "Usable area changed, rearranging output"); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); - arrange_and_commit(output->swayc); + container_set_dirty(output->swayc); } // Arrange non-exlusive surfaces from top->bottom diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a2720885..a9808406 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -492,19 +492,21 @@ static void handle_destroy(struct wl_listener *listener, void *data) { output->wlr_output->data = NULL; free(output); - arrange_and_commit(&root_container); + arrange_windows(&root_container); } static void handle_mode(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, mode); arrange_layers(output); - arrange_and_commit(output->swayc); + arrange_windows(output->swayc); + transaction_commit_dirty(); } static void handle_transform(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, transform); arrange_layers(output); - arrange_and_commit(output->swayc); + arrange_windows(output->swayc); + transaction_commit_dirty(); } static void handle_scale_iterator(struct sway_container *view, void *data) { @@ -515,7 +517,8 @@ static void handle_scale(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, scale); arrange_layers(output); container_descendants(output->swayc, C_VIEW, handle_scale_iterator, NULL); - arrange_and_commit(output->swayc); + arrange_windows(output->swayc); + transaction_commit_dirty(); } struct sway_output *output_from_wlr_output(struct wlr_output *wlr_output) { @@ -584,5 +587,6 @@ void output_enable(struct sway_output *output) { output->damage_destroy.notify = damage_handle_destroy; arrange_layers(output); - arrange_and_commit(&root_container); + arrange_windows(&root_container); + transaction_commit_dirty(); } diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 2b3f87c3..d7ef7130 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -47,7 +47,7 @@ struct sway_transaction_instruction { bool ready; }; -struct sway_transaction *transaction_create() { +static struct sway_transaction *transaction_create() { struct sway_transaction *transaction = calloc(1, sizeof(struct sway_transaction)); transaction->instructions = create_list(); @@ -141,23 +141,8 @@ static void copy_pending_state(struct sway_container *container, } } -static bool transaction_has_container(struct sway_transaction *transaction, +static void transaction_add_container(struct sway_transaction *transaction, struct sway_container *container) { - for (int i = 0; i < transaction->instructions->length; ++i) { - struct sway_transaction_instruction *instruction = - transaction->instructions->items[i]; - if (instruction->container == container) { - return true; - } - } - return false; -} - -void transaction_add_container(struct sway_transaction *transaction, - struct sway_container *container) { - if (transaction_has_container(transaction, container)) { - return; - } struct sway_transaction_instruction *instruction = calloc(1, sizeof(struct sway_transaction_instruction)); instruction->transaction = transaction; @@ -285,7 +270,7 @@ static bool should_configure(struct sway_container *con, return true; } -void transaction_commit(struct sway_transaction *transaction) { +static void transaction_commit(struct sway_transaction *transaction) { wlr_log(WLR_DEBUG, "Transaction %p committing with %i instructions", transaction, transaction->instructions->length); transaction->num_waiting = 0; @@ -418,3 +403,17 @@ struct wlr_texture *transaction_get_saved_texture(struct sway_view *view, *height = instruction->saved_buffer_height; return instruction->saved_buffer->texture; } + +void transaction_commit_dirty() { + if (!server.dirty_containers->length) { + return; + } + struct sway_transaction *transaction = transaction_create(); + for (int i = 0; i < server.dirty_containers->length; ++i) { + struct sway_container *container = server.dirty_containers->items[i]; + transaction_add_container(transaction, container); + container->dirty = false; + } + server.dirty_containers->length = 0; + transaction_commit(transaction); +} diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index fbeeb2e3..98c16faf 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -244,7 +244,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) view_set_fullscreen(view, e->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); + transaction_commit_dirty(); } static void handle_unmap(struct wl_listener *listener, void *data) { @@ -281,10 +282,11 @@ static void handle_map(struct wl_listener *listener, void *data) { if (xdg_surface->toplevel->client_pending.fullscreen) { view_set_fullscreen(view, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_and_commit(ws); + arrange_windows(ws); } else { - arrange_and_commit(view->swayc->parent); + arrange_windows(view->swayc->parent); } + transaction_commit_dirty(); xdg_shell_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 88d9bb94..4d76f0a7 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -239,7 +239,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) view_set_fullscreen(view, e->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); + transaction_commit_dirty(); } static void handle_unmap(struct wl_listener *listener, void *data) { @@ -276,10 +277,11 @@ static void handle_map(struct wl_listener *listener, void *data) { if (xdg_surface->toplevel->client_pending.fullscreen) { view_set_fullscreen(view, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_and_commit(ws); + arrange_windows(ws); } else { - arrange_and_commit(view->swayc->parent); + arrange_windows(view->swayc->parent); } + transaction_commit_dirty(); xdg_shell_v6_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 460d1cc8..11516673 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -333,10 +333,11 @@ static void handle_map(struct wl_listener *listener, void *data) { if (xsurface->fullscreen) { view_set_fullscreen(view, true); struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); - arrange_and_commit(ws); + arrange_windows(ws); } else { - arrange_and_commit(view->swayc->parent); + arrange_windows(view->swayc->parent); } + transaction_commit_dirty(); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -392,7 +393,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) view_set_fullscreen(view, xsurface->fullscreen); struct sway_container *output = container_parent(view->swayc, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); + transaction_commit_dirty(); } static void handle_set_title(struct wl_listener *listener, void *data) { diff --git a/sway/server.c b/sway/server.c index 1d8eb964..8566d512 100644 --- a/sway/server.c +++ b/sway/server.c @@ -125,8 +125,7 @@ bool server_init(struct sway_server *server) { if (debug != NULL && strcmp(debug, "txn_timings") == 0) { server->debug_txn_timings = true; } - server->destroying_containers = create_list(); - + server->dirty_containers = create_list(); server->transactions = create_list(); input_manager = input_manager_create(server); @@ -136,7 +135,7 @@ bool server_init(struct sway_server *server) { void server_fini(struct sway_server *server) { // TODO: free sway-specific resources wl_display_destroy(server->wl_display); - list_free(server->destroying_containers); + list_free(server->dirty_containers); list_free(server->transactions); } diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index bcc3ee9a..533cf71c 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c @@ -144,38 +144,22 @@ static void apply_tabbed_or_stacked_layout(struct sway_container *parent) { } } -/** - * If a container has been deleted from the pending tree state, we must add it - * to the transaction so it can be freed afterwards. To do this, we iterate the - * server's destroying_containers list and add all of them. We may add more than - * what we need to, but this is easy and has no negative consequences. - */ -static void add_deleted_containers(struct sway_transaction *transaction) { - for (int i = 0; i < server.destroying_containers->length; ++i) { - struct sway_container *child = server.destroying_containers->items[i]; - transaction_add_container(transaction, child); - } -} - -static void arrange_children_of(struct sway_container *parent, - struct sway_transaction *transaction); +static void arrange_children_of(struct sway_container *parent); -static void arrange_floating(struct sway_container *floating, - struct sway_transaction *transaction) { +static void arrange_floating(struct sway_container *floating) { for (int i = 0; i < floating->children->length; ++i) { struct sway_container *floater = floating->children->items[i]; if (floater->type == C_VIEW) { view_autoconfigure(floater->sway_view); } else { - arrange_children_of(floater, transaction); + arrange_children_of(floater); } - transaction_add_container(transaction, floater); + container_set_dirty(floater); } - transaction_add_container(transaction, floating); + container_set_dirty(floating); } -static void arrange_children_of(struct sway_container *parent, - struct sway_transaction *transaction) { +static void arrange_children_of(struct sway_container *parent) { if (config->reloading) { return; } @@ -198,7 +182,7 @@ static void arrange_children_of(struct sway_container *parent, apply_horiz_layout(parent); break; case L_FLOATING: - arrange_floating(parent, transaction); + arrange_floating(parent); break; } @@ -213,14 +197,13 @@ static void arrange_children_of(struct sway_container *parent, if (child->type == C_VIEW) { view_autoconfigure(child->sway_view); } else { - arrange_children_of(child, transaction); + arrange_children_of(child); } - transaction_add_container(transaction, child); + container_set_dirty(child); } } -static void arrange_workspace(struct sway_container *workspace, - struct sway_transaction *transaction) { +static void arrange_workspace(struct sway_container *workspace) { if (config->reloading) { return; } @@ -234,15 +217,14 @@ static void arrange_workspace(struct sway_container *workspace, workspace->x = output->x + area->x; workspace->y = output->y + area->y; add_gaps(workspace); - transaction_add_container(transaction, workspace); + container_set_dirty(workspace); wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name, workspace->x, workspace->y); - arrange_floating(workspace->sway_workspace->floating, transaction); - arrange_children_of(workspace, transaction); + arrange_floating(workspace->sway_workspace->floating); + arrange_children_of(workspace); } -static void arrange_output(struct sway_container *output, - struct sway_transaction *transaction) { +static void arrange_output(struct sway_container *output) { if (config->reloading) { return; } @@ -253,16 +235,16 @@ static void arrange_output(struct sway_container *output, output->y = output_box->y; output->width = output_box->width; output->height = output_box->height; - transaction_add_container(transaction, output); + container_set_dirty(output); wlr_log(WLR_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); for (int i = 0; i < output->children->length; ++i) { struct sway_container *workspace = output->children->items[i]; - arrange_workspace(workspace, transaction); + arrange_workspace(workspace); } } -static void arrange_root(struct sway_transaction *transaction) { +static void arrange_root() { if (config->reloading) { return; } @@ -274,43 +256,35 @@ static void arrange_root(struct sway_transaction *transaction) { root_container.y = layout_box->y; root_container.width = layout_box->width; root_container.height = layout_box->height; - transaction_add_container(transaction, &root_container); + container_set_dirty(&root_container); for (int i = 0; i < root_container.children->length; ++i) { struct sway_container *output = root_container.children->items[i]; - arrange_output(output, transaction); + arrange_output(output); } } -void arrange_windows(struct sway_container *container, - struct sway_transaction *transaction) { +void arrange_windows(struct sway_container *container) { switch (container->type) { case C_ROOT: - arrange_root(transaction); + arrange_root(); break; case C_OUTPUT: - arrange_output(container, transaction); + arrange_output(container); break; case C_WORKSPACE: - arrange_workspace(container, transaction); + arrange_workspace(container); break; case C_CONTAINER: - arrange_children_of(container, transaction); - transaction_add_container(transaction, container); + arrange_children_of(container); + container_set_dirty(container); break; case C_VIEW: view_autoconfigure(container->sway_view); - transaction_add_container(transaction, container); + container_set_dirty(container); break; case C_TYPES: break; } - add_deleted_containers(transaction); -} - -void arrange_and_commit(struct sway_container *container) { - struct sway_transaction *transaction = transaction_create(); - arrange_windows(container, transaction); - transaction_commit(transaction); } void remove_gaps(struct sway_container *c) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 58852717..35f67cce 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -159,14 +159,6 @@ void container_free(struct sway_container *cont) { wlr_texture_destroy(cont->title_focused_inactive); wlr_texture_destroy(cont->title_unfocused); wlr_texture_destroy(cont->title_urgent); - - for (int i = 0; i < server.destroying_containers->length; ++i) { - if (server.destroying_containers->items[i] == cont) { - list_del(server.destroying_containers, i); - break; - } - } - list_free(cont->instructions); list_free(cont->children); list_free(cont->current.children); @@ -325,7 +317,7 @@ static struct sway_container *container_destroy_noreaping( } con->destroying = true; - list_add(server.destroying_containers, con); + container_set_dirty(con); if (!con->parent) { return NULL; @@ -1069,9 +1061,15 @@ void container_floating_move_to(struct sway_container *con, if (old_workspace != new_workspace) { container_remove_child(con); container_add_child(new_workspace->sway_workspace->floating, con); - struct sway_transaction *transaction = transaction_create(); - arrange_windows(old_workspace, transaction); - arrange_windows(new_workspace, transaction); - transaction_commit(transaction); + arrange_windows(old_workspace); + arrange_windows(new_workspace); + } +} + +void container_set_dirty(struct sway_container *container) { + if (container->dirty) { + return; } + container->dirty = true; + list_add(server.dirty_containers, container); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ba234e89..54ddb3f9 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -22,7 +22,8 @@ struct sway_container root_container; static void output_layout_handle_change(struct wl_listener *listener, void *data) { - arrange_and_commit(&root_container); + arrange_windows(&root_container); + transaction_commit_dirty(); } void layout_init(void) { diff --git a/sway/tree/view.c b/sway/tree/view.c index b356183c..bf380d98 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -594,11 +594,12 @@ void view_unmap(struct sway_view *view) { ws->sway_workspace->fullscreen = NULL; container_destroy(view->swayc); - arrange_and_commit(ws->parent); + arrange_windows(ws->parent); } else { struct sway_container *parent = container_destroy(view->swayc); - arrange_and_commit(parent); + arrange_windows(parent); } + transaction_commit_dirty(); view->surface = NULL; } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 50f9400a..2a2d834a 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -427,7 +427,7 @@ bool workspace_switch(struct sway_container *workspace) { } seat_set_focus(seat, next); struct sway_container *output = container_parent(workspace, C_OUTPUT); - arrange_and_commit(output); + arrange_windows(output); return true; } -- cgit v1.2.3 From e6209afcd6923d9803c3ea6bacf3f9322a7a7450 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 15 Jul 2018 14:59:54 +0100 Subject: Fix config buffer overflow and logic --- sway/config.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index 636f5f57..b8c874e6 100644 --- a/sway/config.c +++ b/sway/config.c @@ -560,8 +560,8 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { bool read_config(FILE *file, struct sway_config *config) { bool reading_main_config = false; - char *this_config = NULL, *config_pos; - long config_size = 0; + char *this_config = NULL; + unsigned long config_size = 0; if (config->current_config == NULL) { reading_main_config = true; @@ -569,7 +569,7 @@ bool read_config(FILE *file, struct sway_config *config) { config_size = ftell(file); rewind(file); - config_pos = this_config = malloc(config_size + 1); + config->current_config = this_config = calloc(1, config_size + 1); if (this_config == NULL) { wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); return false; @@ -580,6 +580,7 @@ bool read_config(FILE *file, struct sway_config *config) { int line_number = 0; char *line; list_t *stack = create_list(); + size_t read = 0; while (!feof(file)) { char *block = stack->length ? stack->items[0] : NULL; line = read_line(file); @@ -590,10 +591,21 @@ bool read_config(FILE *file, struct sway_config *config) { wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); if (reading_main_config) { - size_t l = strlen(line); - memcpy(config_pos, line, l); // don't copy terminating character - config_pos += l; - *config_pos++ = '\n'; + size_t length = strlen(line); + + if (read + length > config_size) { + wlr_log(WLR_ERROR, "Config file changed during reading"); + list_foreach(stack, free); + list_free(stack); + free(line); + return false; + } + + strcpy(this_config + read, line); + if (line_number != 1) { + this_config[read - 1] = '\n'; + } + read += length + 1; } line = strip_whitespace(line); @@ -616,7 +628,6 @@ bool read_config(FILE *file, struct sway_config *config) { list_foreach(stack, free); list_free(stack); free(line); - free(this_config); return false; } wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); @@ -677,10 +688,6 @@ bool read_config(FILE *file, struct sway_config *config) { list_foreach(stack, free); list_free(stack); - if (reading_main_config) { - this_config[config_size - 1] = '\0'; - config->current_config = this_config; - } return success; } -- cgit v1.2.3 From 011d43746faf1bb2a6619e1246143724eb253b52 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 15 Jul 2018 15:36:51 +0100 Subject: Add error handling for getting config file size --- sway/config.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index b8c874e6..2c051146 100644 --- a/sway/config.c +++ b/sway/config.c @@ -561,12 +561,17 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { bool read_config(FILE *file, struct sway_config *config) { bool reading_main_config = false; char *this_config = NULL; - unsigned long config_size = 0; + size_t config_size = 0; if (config->current_config == NULL) { reading_main_config = true; - fseek(file, 0, SEEK_END); - config_size = ftell(file); + int ret_seek = fseek(file, 0, SEEK_END); + long ret_tell = ftell(file); + if (ret_seek == -1 || ret_tell == -1) { + wlr_log(WLR_ERROR, "Unable to get size of config file"); + return false; + } + config_size = ret_tell; rewind(file); config->current_config = this_config = calloc(1, config_size + 1); -- cgit v1.2.3 From 92450883d7b148d408b42c3553a60340a14771f6 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 15 Jul 2018 21:48:39 +0100 Subject: config: free include path on successful load --- sway/config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index 2c051146..f63835bf 100644 --- a/sway/config.c +++ b/sway/config.c @@ -474,6 +474,7 @@ static bool load_include_config(const char *path, const char *parent_dir, list_del(config->config_chain, index); return false; } + free(real_path); // restore current_config_path config->current_config_path = parent_config; -- cgit v1.2.3 From db3a36373435a34b8d0a5fc4e90eacaa2b1dae6b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 16 Jul 2018 21:00:57 -0400 Subject: Revert "config: free include path on successful load" This reverts commit 92450883d7b148d408b42c3553a60340a14771f6. --- sway/config.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index f63835bf..2c051146 100644 --- a/sway/config.c +++ b/sway/config.c @@ -474,7 +474,6 @@ static bool load_include_config(const char *path, const char *parent_dir, list_del(config->config_chain, index); return false; } - free(real_path); // restore current_config_path config->current_config_path = parent_config; -- cgit v1.2.3 From 600676688a47bde05bc12110818127c5300dd876 Mon Sep 17 00:00:00 2001 From: frsfnrrg Date: Tue, 17 Jul 2018 11:19:32 -0400 Subject: Free individual criteria in free_config Also free cmd_list when cleaning up a struct criteria. --- sway/config.c | 8 +++++++- sway/criteria.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'sway/config.c') diff --git a/sway/config.c b/sway/config.c index 2c051146..c620e4c7 100644 --- a/sway/config.c +++ b/sway/config.c @@ -24,6 +24,7 @@ #include "sway/input/seat.h" #include "sway/commands.h" #include "sway/config.h" +#include "sway/criteria.h" #include "sway/tree/arrange.h" #include "sway/tree/layout.h" #include "sway/tree/workspace.h" @@ -105,7 +106,12 @@ void free_config(struct sway_config *config) { } list_free(config->seat_configs); } - list_free(config->criteria); + if (config->criteria) { + for (int i = 0; i < config->criteria->length; ++i) { + criteria_destroy(config->criteria->items[i]); + } + list_free(config->criteria); + } list_free(config->no_focus); list_free(config->active_bar_modifiers); list_free(config->config_chain); diff --git a/sway/criteria.c b/sway/criteria.c index c999d248..e2b248de 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -37,7 +37,7 @@ void criteria_destroy(struct criteria *criteria) { pcre_free(criteria->con_mark); pcre_free(criteria->window_role); free(criteria->workspace); - + free(criteria->cmdlist); free(criteria->raw); free(criteria); } -- cgit v1.2.3