@@ -79,6 +79,71 @@ struct output_config *new_output_config(const char *name) {
79
79
return oc ;
80
80
}
81
81
82
+ // supersede_output_config clears all fields in dst that were set in src
83
+ static void supersede_output_config (struct output_config * dst , struct output_config * src ) {
84
+ if (src -> enabled != -1 ) {
85
+ dst -> enabled = -1 ;
86
+ }
87
+ if (src -> width != -1 ) {
88
+ dst -> width = -1 ;
89
+ }
90
+ if (src -> height != -1 ) {
91
+ dst -> height = -1 ;
92
+ }
93
+ if (src -> x != -1 ) {
94
+ dst -> x = -1 ;
95
+ }
96
+ if (src -> y != -1 ) {
97
+ dst -> y = -1 ;
98
+ }
99
+ if (src -> scale != -1 ) {
100
+ dst -> scale = -1 ;
101
+ }
102
+ if (src -> scale_filter != SCALE_FILTER_DEFAULT ) {
103
+ dst -> scale_filter = SCALE_FILTER_DEFAULT ;
104
+ }
105
+ if (src -> subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN ) {
106
+ dst -> subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN ;
107
+ }
108
+ if (src -> refresh_rate != -1 ) {
109
+ dst -> refresh_rate = -1 ;
110
+ }
111
+ if (src -> custom_mode != -1 ) {
112
+ dst -> custom_mode = -1 ;
113
+ }
114
+ if (src -> drm_mode .type != (uint32_t ) -1 ) {
115
+ dst -> drm_mode .type = -1 ;
116
+ }
117
+ if (src -> transform != -1 ) {
118
+ dst -> transform = -1 ;
119
+ }
120
+ if (src -> max_render_time != -1 ) {
121
+ dst -> max_render_time = -1 ;
122
+ }
123
+ if (src -> adaptive_sync != -1 ) {
124
+ dst -> adaptive_sync = -1 ;
125
+ }
126
+ if (src -> render_bit_depth != RENDER_BIT_DEPTH_DEFAULT ) {
127
+ dst -> render_bit_depth = RENDER_BIT_DEPTH_DEFAULT ;
128
+ }
129
+ if (src -> background ) {
130
+ free (dst -> background );
131
+ dst -> background = NULL ;
132
+ }
133
+ if (src -> background_option ) {
134
+ free (dst -> background_option );
135
+ dst -> background_option = NULL ;
136
+ }
137
+ if (src -> background_fallback ) {
138
+ free (dst -> background_fallback );
139
+ dst -> background_fallback = NULL ;
140
+ }
141
+ if (src -> power != -1 ) {
142
+ dst -> power = -1 ;
143
+ }
144
+ }
145
+
146
+ // merge_output_config sets all fields in dst that were set in src
82
147
static void merge_output_config (struct output_config * dst , struct output_config * src ) {
83
148
if (src -> enabled != -1 ) {
84
149
dst -> enabled = src -> enabled ;
@@ -142,94 +207,49 @@ static void merge_output_config(struct output_config *dst, struct output_config
142
207
}
143
208
}
144
209
145
- static void merge_wildcard_on_all (struct output_config * wildcard ) {
146
- for (int i = 0 ; i < config -> output_configs -> length ; i ++ ) {
147
- struct output_config * oc = config -> output_configs -> items [i ];
148
- if (strcmp (wildcard -> name , oc -> name ) != 0 ) {
149
- sway_log (SWAY_DEBUG , "Merging output * config on %s" , oc -> name );
150
- merge_output_config (oc , wildcard );
151
- }
152
- }
153
- }
210
+ // store_output_config stores a new output config. An output may be matched by
211
+ // three different config types, in order of precedence: Identifier, name and
212
+ // wildcard. When storing a config type of lower precedence, assume that the
213
+ // user wants the config to take immediate effect by clearing the same values
214
+ // from higher presedence configuration.
215
+ void store_output_config (struct output_config * oc ) {
154
216
155
- static void merge_id_on_name (struct output_config * oc ) {
156
- struct sway_output * output = all_output_by_name_or_id (oc -> name );
157
- if (output == NULL ) {
158
- return ;
159
- }
160
-
161
- const char * name = output -> wlr_output -> name ;
217
+ // Find the output that this configuration will apply to.
162
218
char id [128 ];
163
- output_get_identifier (id , sizeof (id ), output );
164
-
165
- char * id_on_name = format_str ("%s on %s" , id , name );
166
- if (!id_on_name ) {
167
- return ;
219
+ bool merged = false, is_name = false;
220
+ bool wildcard = strcmp (oc -> name , "*" ) == 0 ;
221
+ struct sway_output * output = wildcard ? NULL : output_by_name_or_id (oc -> name );
222
+ if (output ) {
223
+ output_get_identifier (id , sizeof (id ), output );
224
+ is_name = strcmp (oc -> name , output -> wlr_output -> name ) == 0 ;
225
+ } else if (!wildcard ) {
226
+ // There is no config by this name, just add it in
227
+ goto done ;
168
228
}
169
229
170
- int i = list_seq_find (config -> output_configs , output_name_cmp , id_on_name );
171
- if (i >= 0 ) {
172
- sway_log (SWAY_DEBUG , "Merging on top of existing id on name config" );
173
- merge_output_config (config -> output_configs -> items [i ], oc );
174
- } else {
175
- // If both a name and identifier config, exist generate an id on name
176
- int ni = list_seq_find (config -> output_configs , output_name_cmp , name );
177
- int ii = list_seq_find (config -> output_configs , output_name_cmp , id );
178
- if ((ni >= 0 && ii >= 0 ) || (ni >= 0 && strcmp (oc -> name , id ) == 0 )
179
- || (ii >= 0 && strcmp (oc -> name , name ) == 0 )) {
180
- struct output_config * ion_oc = new_output_config (id_on_name );
181
- if (ni >= 0 ) {
182
- merge_output_config (ion_oc , config -> output_configs -> items [ni ]);
183
- }
184
- if (ii >= 0 ) {
185
- merge_output_config (ion_oc , config -> output_configs -> items [ii ]);
186
- }
187
- merge_output_config (ion_oc , oc );
188
- list_add (config -> output_configs , ion_oc );
189
- sway_log (SWAY_DEBUG , "Generated id on name output config \"%s\""
190
- " (enabled: %d) (%dx%d@%fHz position %d,%d scale %f "
191
- "transform %d) (bg %s %s) (power %d) (max render time: %d)" ,
192
- ion_oc -> name , ion_oc -> enabled , ion_oc -> width , ion_oc -> height ,
193
- ion_oc -> refresh_rate , ion_oc -> x , ion_oc -> y , ion_oc -> scale ,
194
- ion_oc -> transform , ion_oc -> background ,
195
- ion_oc -> background_option , ion_oc -> power ,
196
- ion_oc -> max_render_time );
230
+ // If the configuration matches the output by name, merge with existing
231
+ // name configuration and clear identifier configuration. If the
232
+ // configuration matches the output by identifier, merge with existing
233
+ // identifier configuration.
234
+ for (int i = 0 ; i < config -> output_configs -> length ; i ++ ) {
235
+ struct output_config * old = config -> output_configs -> items [i ];
236
+ if (strcmp (old -> name , oc -> name ) == 0 ) {
237
+ merge_output_config (old , oc );
238
+ merged = true;
239
+ continue ;
197
240
}
198
- }
199
- free (id_on_name );
200
- }
241
+ bool matches_identifier = output && strcmp (old -> name , id ) == 0 ;
201
242
202
- struct output_config * store_output_config (struct output_config * oc ) {
203
- bool wildcard = strcmp (oc -> name , "*" ) == 0 ;
204
- if (wildcard ) {
205
- merge_wildcard_on_all (oc );
206
- } else {
207
- merge_id_on_name (oc );
243
+ if (wildcard || (is_name && matches_identifier )) {
244
+ supersede_output_config (old , oc );
245
+ }
208
246
}
209
247
210
- int i = list_seq_find (config -> output_configs , output_name_cmp , oc -> name );
211
- if (i >= 0 ) {
212
- sway_log (SWAY_DEBUG , "Merging on top of existing output config" );
213
- struct output_config * current = config -> output_configs -> items [i ];
214
- merge_output_config (current , oc );
215
- free_output_config (oc );
216
- oc = current ;
217
- } else if (!wildcard ) {
218
- sway_log (SWAY_DEBUG , "Adding non-wildcard output config" );
219
- i = list_seq_find (config -> output_configs , output_name_cmp , "*" );
220
- if (i >= 0 ) {
221
- sway_log (SWAY_DEBUG , "Merging on top of output * config" );
222
- struct output_config * current = new_output_config (oc -> name );
223
- merge_output_config (current , config -> output_configs -> items [i ]);
224
- merge_output_config (current , oc );
225
- free_output_config (oc );
226
- oc = current ;
227
- }
248
+ done :
249
+ if (!merged ) {
228
250
list_add (config -> output_configs , oc );
229
251
} else {
230
- // New wildcard config. Just add it
231
- sway_log (SWAY_DEBUG , "Adding output * config" );
232
- list_add (config -> output_configs , oc );
252
+ free_output_config (oc );
233
253
}
234
254
235
255
sway_log (SWAY_DEBUG , "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
@@ -239,8 +259,6 @@ struct output_config *store_output_config(struct output_config *oc) {
239
259
oc -> x , oc -> y , oc -> scale , sway_wl_output_subpixel_to_string (oc -> subpixel ),
240
260
oc -> transform , oc -> background , oc -> background_option , oc -> power ,
241
261
oc -> max_render_time );
242
-
243
- return oc ;
244
262
}
245
263
246
264
static void set_mode (struct wlr_output * output , struct wlr_output_state * pending ,
@@ -587,96 +605,49 @@ static void default_output_config(struct output_config *oc,
587
605
oc -> max_render_time = 0 ;
588
606
}
589
607
590
- static struct output_config * get_output_config (char * identifier ,
591
- struct sway_output * sway_output ) {
608
+ // find_output_config returns a merged output_config containing all stored
609
+ // configuration that applies to the specified output.
610
+ struct output_config * find_output_config (struct sway_output * sway_output ) {
592
611
const char * name = sway_output -> wlr_output -> name ;
612
+ struct output_config * oc = NULL ;
593
613
594
- struct output_config * oc_id_on_name = NULL ;
595
- struct output_config * oc_name = NULL ;
596
- struct output_config * oc_id = NULL ;
597
-
598
- char * id_on_name = format_str ("%s on %s" , identifier , name );
599
- int i = list_seq_find (config -> output_configs , output_name_cmp , id_on_name );
600
- if (i >= 0 ) {
601
- oc_id_on_name = config -> output_configs -> items [i ];
602
- } else {
603
- i = list_seq_find (config -> output_configs , output_name_cmp , name );
604
- if (i >= 0 ) {
605
- oc_name = config -> output_configs -> items [i ];
606
- }
607
-
608
- i = list_seq_find (config -> output_configs , output_name_cmp , identifier );
609
- if (i >= 0 ) {
610
- oc_id = config -> output_configs -> items [i ];
611
- }
612
- }
613
-
614
- struct output_config * result = new_output_config ("temp" );
614
+ struct output_config * result = new_output_config (name );
615
615
if (config -> reloading ) {
616
616
default_output_config (result , sway_output -> wlr_output );
617
617
}
618
- if (oc_id_on_name ) {
619
- // Already have an identifier on name config, use that
620
- free (result -> name );
621
- result -> name = strdup (id_on_name );
622
- merge_output_config (result , oc_id_on_name );
623
- } else if (oc_name && oc_id ) {
624
- // Generate a config named `<identifier> on <name>` which contains a
625
- // merged copy of the identifier on name. This will make sure that both
626
- // identifier and name configs are respected, with identifier getting
627
- // priority
628
- struct output_config * temp = new_output_config (id_on_name );
629
- merge_output_config (temp , oc_name );
630
- merge_output_config (temp , oc_id );
631
- list_add (config -> output_configs , temp );
632
-
633
- free (result -> name );
634
- result -> name = strdup (id_on_name );
635
- merge_output_config (result , temp );
636
-
637
- sway_log (SWAY_DEBUG , "Generated output config \"%s\" (enabled: %d)"
638
- " (%dx%d@%fHz position %d,%d scale %f transform %d) (bg %s %s)"
639
- " (power %d) (max render time: %d)" , result -> name , result -> enabled ,
640
- result -> width , result -> height , result -> refresh_rate ,
641
- result -> x , result -> y , result -> scale , result -> transform ,
642
- result -> background , result -> background_option , result -> power ,
643
- result -> max_render_time );
644
- } else if (oc_name ) {
645
- // No identifier config, just return a copy of the name config
646
- free (result -> name );
647
- result -> name = strdup (name );
648
- merge_output_config (result , oc_name );
649
- } else if (oc_id ) {
650
- // No name config, just return a copy of the identifier config
651
- free (result -> name );
652
- result -> name = strdup (identifier );
653
- merge_output_config (result , oc_id );
654
- } else {
655
- i = list_seq_find (config -> output_configs , output_name_cmp , "*" );
656
- if (i >= 0 ) {
657
- // No name or identifier config, but there is a wildcard config
658
- free (result -> name );
659
- result -> name = strdup ("*" );
660
- merge_output_config (result , config -> output_configs -> items [i ]);
661
- } else if (!config -> reloading ) {
662
- // No name, identifier, or wildcard config. Since we are not
663
- // reloading with defaults, the output config will be empty, so
664
- // just return NULL
665
- free_output_config (result );
666
- result = NULL ;
667
- }
618
+
619
+ char id [128 ];
620
+ output_get_identifier (id , sizeof (id ), sway_output );
621
+
622
+ int i ;
623
+ bool match = false;
624
+ if ((i = list_seq_find (config -> output_configs , output_name_cmp , "*" )) >= 0 ) {
625
+ match = true;
626
+ oc = config -> output_configs -> items [i ];
627
+ merge_output_config (result , oc );
628
+ }
629
+ if ((i = list_seq_find (config -> output_configs , output_name_cmp , name )) >= 0 ) {
630
+ match = true;
631
+ oc = config -> output_configs -> items [i ];
632
+ merge_output_config (result , oc );
633
+ }
634
+ if ((i = list_seq_find (config -> output_configs , output_name_cmp , id )) >= 0 ) {
635
+ match = true;
636
+ oc = config -> output_configs -> items [i ];
637
+ merge_output_config (result , oc );
638
+ }
639
+
640
+ if (!match && !config -> reloading ) {
641
+ // No name, identifier, or wildcard config. Since we are not
642
+ // reloading with defaults, the output config will be empty, so
643
+ // just return NULL
644
+ free_output_config (result );
645
+ return NULL ;
668
646
}
669
647
670
- free (id_on_name );
671
648
return result ;
672
649
}
673
650
674
- struct output_config * find_output_config (struct sway_output * output ) {
675
- char id [128 ];
676
- output_get_identifier (id , sizeof (id ), output );
677
- return get_output_config (id , output );
678
- }
679
-
680
651
bool apply_output_configs (struct matched_output_config * configs , size_t configs_len ) {
681
652
struct wlr_backend_output_state * states = calloc (configs_len , sizeof (* states ));
682
653
if (!states ) {
0 commit comments