Skip to content

Commit 55e2b5e

Browse files
committed
Allow all glob patters in output configs
Instead of special casing "output * ..." just make output take all glob patterns. This is implemented by just storing all output commands unaltered and then matching the glob patterns to the outputs whenever needed. Match order is the same as command introduction order so that any newer commands are always respected.
1 parent 6991ac8 commit 55e2b5e

File tree

3 files changed

+30
-221
lines changed

3 files changed

+30
-221
lines changed

include/sway/config.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ struct output_config *store_output_config(struct output_config *oc);
644644

645645
struct output_config *find_output_config(struct sway_output *output);
646646

647-
void apply_output_config_to_outputs(struct output_config *oc);
647+
void apply_output_config_to_outputs();
648648

649649
void reset_outputs(void);
650650

sway/commands/output.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,13 @@ struct cmd_results *cmd_output(int argc, char **argv) {
9999

100100
bool background = output->background;
101101

102-
output = store_output_config(output);
102+
store_output_config(output);
103103

104104
// If reloading, the output configs will be applied after reading the
105105
// entire config and before the deferred commands so that an auto generated
106106
// workspace name is not given to re-enabled outputs.
107107
if (!config->reloading && !config->validating) {
108-
apply_output_config_to_outputs(output);
108+
apply_output_config_to_outputs();
109109
if (background) {
110110
spawn_swaybg();
111111
}

sway/config/output.c

+27-218
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <sys/socket.h>
66
#include <sys/wait.h>
77
#include <unistd.h>
8+
#include <fnmatch.h>
89
#include <wlr/types/wlr_cursor.h>
910
#include <wlr/types/wlr_output_layout.h>
1011
#include <wlr/types/wlr_output.h>
@@ -15,13 +16,6 @@
1516
#include "log.h"
1617
#include "util.h"
1718

18-
int output_name_cmp(const void *item, const void *data) {
19-
const struct output_config *output = item;
20-
const char *name = data;
21-
22-
return strcmp(output->name, name);
23-
}
24-
2519
void output_get_identifier(char *identifier, size_t len,
2620
struct sway_output *output) {
2721
struct wlr_output *wlr_output = output->wlr_output;
@@ -125,104 +119,8 @@ void merge_output_config(struct output_config *dst, struct output_config *src) {
125119
}
126120
}
127121

128-
static void merge_wildcard_on_all(struct output_config *wildcard) {
129-
for (int i = 0; i < config->output_configs->length; i++) {
130-
struct output_config *oc = config->output_configs->items[i];
131-
if (strcmp(wildcard->name, oc->name) != 0) {
132-
sway_log(SWAY_DEBUG, "Merging output * config on %s", oc->name);
133-
merge_output_config(oc, wildcard);
134-
}
135-
}
136-
}
137-
138-
static void merge_id_on_name(struct output_config *oc) {
139-
char *id_on_name = NULL;
140-
char id[128];
141-
char *name = NULL;
142-
struct sway_output *output;
143-
wl_list_for_each(output, &root->all_outputs, link) {
144-
name = output->wlr_output->name;
145-
output_get_identifier(id, sizeof(id), output);
146-
if (strcmp(name, oc->name) == 0 || strcmp(id, oc->name) == 0) {
147-
size_t length = snprintf(NULL, 0, "%s on %s", id, name) + 1;
148-
id_on_name = malloc(length);
149-
if (!id_on_name) {
150-
sway_log(SWAY_ERROR, "Failed to allocate id on name string");
151-
return;
152-
}
153-
snprintf(id_on_name, length, "%s on %s", id, name);
154-
break;
155-
}
156-
}
157-
158-
if (!id_on_name) {
159-
return;
160-
}
161-
162-
int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name);
163-
if (i >= 0) {
164-
sway_log(SWAY_DEBUG, "Merging on top of existing id on name config");
165-
merge_output_config(config->output_configs->items[i], oc);
166-
} else {
167-
// If both a name and identifier config, exist generate an id on name
168-
int ni = list_seq_find(config->output_configs, output_name_cmp, name);
169-
int ii = list_seq_find(config->output_configs, output_name_cmp, id);
170-
if ((ni >= 0 && ii >= 0) || (ni >= 0 && strcmp(oc->name, id) == 0)
171-
|| (ii >= 0 && strcmp(oc->name, name) == 0)) {
172-
struct output_config *ion_oc = new_output_config(id_on_name);
173-
if (ni >= 0) {
174-
merge_output_config(ion_oc, config->output_configs->items[ni]);
175-
}
176-
if (ii >= 0) {
177-
merge_output_config(ion_oc, config->output_configs->items[ii]);
178-
}
179-
merge_output_config(ion_oc, oc);
180-
list_add(config->output_configs, ion_oc);
181-
sway_log(SWAY_DEBUG, "Generated id on name output config \"%s\""
182-
" (enabled: %d) (%dx%d@%fHz position %d,%d scale %f "
183-
"transform %d) (bg %s %s) (dpms %d) (max render time: %d)",
184-
ion_oc->name, ion_oc->enabled, ion_oc->width, ion_oc->height,
185-
ion_oc->refresh_rate, ion_oc->x, ion_oc->y, ion_oc->scale,
186-
ion_oc->transform, ion_oc->background,
187-
ion_oc->background_option, ion_oc->dpms_state,
188-
ion_oc->max_render_time);
189-
}
190-
}
191-
free(id_on_name);
192-
}
193-
194122
struct output_config *store_output_config(struct output_config *oc) {
195-
bool wildcard = strcmp(oc->name, "*") == 0;
196-
if (wildcard) {
197-
merge_wildcard_on_all(oc);
198-
} else {
199-
merge_id_on_name(oc);
200-
}
201-
202-
int i = list_seq_find(config->output_configs, output_name_cmp, oc->name);
203-
if (i >= 0) {
204-
sway_log(SWAY_DEBUG, "Merging on top of existing output config");
205-
struct output_config *current = config->output_configs->items[i];
206-
merge_output_config(current, oc);
207-
free_output_config(oc);
208-
oc = current;
209-
} else if (!wildcard) {
210-
sway_log(SWAY_DEBUG, "Adding non-wildcard output config");
211-
i = list_seq_find(config->output_configs, output_name_cmp, "*");
212-
if (i >= 0) {
213-
sway_log(SWAY_DEBUG, "Merging on top of output * config");
214-
struct output_config *current = new_output_config(oc->name);
215-
merge_output_config(current, config->output_configs->items[i]);
216-
merge_output_config(current, oc);
217-
free_output_config(oc);
218-
oc = current;
219-
}
220-
list_add(config->output_configs, oc);
221-
} else {
222-
// New wildcard config. Just add it
223-
sway_log(SWAY_DEBUG, "Adding output * config");
224-
list_add(config->output_configs, oc);
225-
}
123+
list_add(config->output_configs, oc);
226124

227125
sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
228126
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (dpms %d) "
@@ -513,125 +411,43 @@ static void default_output_config(struct output_config *oc,
513411
oc->max_render_time = 0;
514412
}
515413

516-
static struct output_config *get_output_config(char *identifier,
517-
struct sway_output *sway_output) {
518-
const char *name = sway_output->wlr_output->name;
519-
520-
struct output_config *oc_id_on_name = NULL;
521-
struct output_config *oc_name = NULL;
522-
struct output_config *oc_id = NULL;
523-
524-
size_t length = snprintf(NULL, 0, "%s on %s", identifier, name) + 1;
525-
char *id_on_name = malloc(length);
526-
snprintf(id_on_name, length, "%s on %s", identifier, name);
527-
int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name);
528-
if (i >= 0) {
529-
oc_id_on_name = config->output_configs->items[i];
530-
} else {
531-
i = list_seq_find(config->output_configs, output_name_cmp, name);
532-
if (i >= 0) {
533-
oc_name = config->output_configs->items[i];
534-
}
414+
struct output_config *find_output_config(struct sway_output *sway_output) {
415+
// Start with a default config for this output
416+
struct output_config *result = new_output_config("merge");
417+
default_output_config(result, sway_output->wlr_output);
535418

536-
i = list_seq_find(config->output_configs, output_name_cmp, identifier);
537-
if (i >= 0) {
538-
oc_id = config->output_configs->items[i];
419+
// Apply all matches in order
420+
char id[128];
421+
output_get_identifier(id, sizeof(id), sway_output);
422+
char *name = sway_output->wlr_output->name;
423+
for (int i = 0; i < config->output_configs->length; ++i) {
424+
struct output_config *oc = config->output_configs->items[i];
425+
if (!fnmatch(oc->name, name, 0) || !fnmatch(oc->name, id, 0)) {
426+
merge_output_config(result, oc);
539427
}
540428
}
541429

542-
struct output_config *result = new_output_config("temp");
543-
if (config->reloading) {
544-
default_output_config(result, sway_output->wlr_output);
545-
}
546-
if (oc_id_on_name) {
547-
// Already have an identifier on name config, use that
548-
free(result->name);
549-
result->name = strdup(id_on_name);
550-
merge_output_config(result, oc_id_on_name);
551-
} else if (oc_name && oc_id) {
552-
// Generate a config named `<identifier> on <name>` which contains a
553-
// merged copy of the identifier on name. This will make sure that both
554-
// identifier and name configs are respected, with identifier getting
555-
// priority
556-
struct output_config *temp = new_output_config(id_on_name);
557-
merge_output_config(temp, oc_name);
558-
merge_output_config(temp, oc_id);
559-
list_add(config->output_configs, temp);
560-
561-
free(result->name);
562-
result->name = strdup(id_on_name);
563-
merge_output_config(result, temp);
564-
565-
sway_log(SWAY_DEBUG, "Generated output config \"%s\" (enabled: %d)"
566-
" (%dx%d@%fHz position %d,%d scale %f transform %d) (bg %s %s)"
567-
" (dpms %d) (max render time: %d)", result->name, result->enabled,
568-
result->width, result->height, result->refresh_rate,
569-
result->x, result->y, result->scale, result->transform,
570-
result->background, result->background_option, result->dpms_state,
571-
result->max_render_time);
572-
} else if (oc_name) {
573-
// No identifier config, just return a copy of the name config
574-
free(result->name);
575-
result->name = strdup(name);
576-
merge_output_config(result, oc_name);
577-
} else if (oc_id) {
578-
// No name config, just return a copy of the identifier config
579-
free(result->name);
580-
result->name = strdup(identifier);
581-
merge_output_config(result, oc_id);
582-
} else {
583-
i = list_seq_find(config->output_configs, output_name_cmp, "*");
584-
if (i >= 0) {
585-
// No name or identifier config, but there is a wildcard config
586-
free(result->name);
587-
result->name = strdup("*");
588-
merge_output_config(result, config->output_configs->items[i]);
589-
} else if (!config->reloading) {
590-
// No name, identifier, or wildcard config. Since we are not
591-
// reloading with defaults, the output config will be empty, so
592-
// just return NULL
593-
free_output_config(result);
594-
result = NULL;
595-
}
596-
}
430+
struct output_config *oc = result;
431+
sway_log(SWAY_DEBUG, "Found output config %s (enabled: %d) (%dx%d@%fHz "
432+
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (dpms %d) "
433+
"(max render time: %d)",
434+
oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
435+
oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel),
436+
oc->transform, oc->background, oc->background_option, oc->dpms_state,
437+
oc->max_render_time);
597438

598-
free(id_on_name);
599439
return result;
600440
}
601441

602-
struct output_config *find_output_config(struct sway_output *output) {
603-
char id[128];
604-
output_get_identifier(id, sizeof(id), output);
605-
return get_output_config(id, output);
606-
}
607-
608-
void apply_output_config_to_outputs(struct output_config *oc) {
442+
void apply_output_config_to_outputs(void) {
609443
// Try to find the output container and apply configuration now. If
610444
// this is during startup then there will be no container and config
611445
// will be applied during normal "new output" event from wlroots.
612-
bool wildcard = strcmp(oc->name, "*") == 0;
613-
char id[128];
614446
struct sway_output *sway_output, *tmp;
615447
wl_list_for_each_safe(sway_output, tmp, &root->all_outputs, link) {
616-
char *name = sway_output->wlr_output->name;
617-
output_get_identifier(id, sizeof(id), sway_output);
618-
if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) {
619-
struct output_config *current = get_output_config(id, sway_output);
620-
if (!current) {
621-
// No stored output config matched, apply oc directly
622-
sway_log(SWAY_DEBUG, "Applying oc directly");
623-
current = new_output_config(oc->name);
624-
merge_output_config(current, oc);
625-
}
626-
apply_output_config(current, sway_output);
627-
free_output_config(current);
628-
629-
if (!wildcard) {
630-
// Stop looking if the output config isn't applicable to all
631-
// outputs
632-
break;
633-
}
634-
}
448+
struct output_config *oc = find_output_config(sway_output);
449+
apply_output_config(oc, sway_output);
450+
free_output_config(oc);
635451
}
636452

637453
struct sway_seat *seat;
@@ -642,14 +458,7 @@ void apply_output_config_to_outputs(struct output_config *oc) {
642458
}
643459

644460
void reset_outputs(void) {
645-
struct output_config *oc = NULL;
646-
int i = list_seq_find(config->output_configs, output_name_cmp, "*");
647-
if (i >= 0) {
648-
oc = config->output_configs->items[i];
649-
} else {
650-
oc = store_output_config(new_output_config("*"));
651-
}
652-
apply_output_config_to_outputs(oc);
461+
apply_output_config_to_outputs();
653462
}
654463

655464
void free_output_config(struct output_config *oc) {

0 commit comments

Comments
 (0)