load_layout: Correctly mark non-leaf containers

Example problematic layout:
    {
        "layout": "splith",
        "marks": ["H1"],
        "nodes": [
            {
                "swallows": [
                    {
                        "class": "^a$"
                    }
                ]
            }
        ]
    }

Since the marks were added to the json_node during end_map, the
container that ended up getting the "H1" mark was the child instead of
the parent.
This commit is contained in:
Orestis Floros 2018-11-07 01:06:20 +02:00
parent 3649ecb71e
commit eb53ec83b9
No known key found for this signature in database
GPG Key ID: E9AD9F32E401E38F
1 changed files with 16 additions and 5 deletions

View File

@ -31,7 +31,15 @@ static bool parsing_marks;
struct Match *current_swallow; struct Match *current_swallow;
static bool swallow_is_empty; static bool swallow_is_empty;
static int num_marks; static int num_marks;
static char **marks; /* We need to save each container that needs to be marked if we want to support
* marking non-leaf containers. In their case, the end_map for their children is
* called before their own end_map, so marking json_node would end up marking
* the latest child. We can't just mark containers immediately after we parse a
* mark because of #2511. */
struct pending_marks {
char *mark;
Con *con_to_be_marked;
} * marks;
/* This list is used for reordering the focus stack after parsing the 'focus' /* This list is used for reordering the focus stack after parsing the 'focus'
* array. */ * array. */
@ -149,8 +157,10 @@ static int json_end_map(void *ctx) {
if (num_marks > 0) { if (num_marks > 0) {
for (int i = 0; i < num_marks; i++) { for (int i = 0; i < num_marks; i++) {
con_mark(json_node, marks[i], MM_ADD); Con *con = marks[i].con_to_be_marked;
free(marks[i]); char *mark = marks[i].mark;
con_mark(con, mark, MM_ADD);
free(mark);
} }
FREE(marks); FREE(marks);
@ -274,8 +284,9 @@ static int json_string(void *ctx, const unsigned char *val, size_t len) {
char *mark; char *mark;
sasprintf(&mark, "%.*s", (int)len, val); sasprintf(&mark, "%.*s", (int)len, val);
marks = srealloc(marks, (++num_marks) * sizeof(char *)); marks = srealloc(marks, (++num_marks) * sizeof(struct pending_marks));
marks[num_marks - 1] = sstrdup(mark); marks[num_marks - 1].mark = sstrdup(mark);
marks[num_marks - 1].con_to_be_marked = json_node;
} else { } else {
if (strcasecmp(last_key, "name") == 0) { if (strcasecmp(last_key, "name") == 0) {
json_node->name = scalloc(len + 1, 1); json_node->name = scalloc(len + 1, 1);