diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-07-23 20:27:56 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-07-23 20:31:11 -0400 |
commit | f4b882475eee7a81c206c7825616cc4656b2f60b (patch) | |
tree | 38e6ebf81b235424f105dcbcbb194e5e9eac70c0 /sway/config/output.c | |
parent | Implement pid->workspace tracking (diff) | |
parent | Merge pull request #2342 from RyanDwyer/update-cursor (diff) | |
download | sway-f4b882475eee7a81c206c7825616cc4656b2f60b.tar.gz sway-f4b882475eee7a81c206c7825616cc4656b2f60b.tar.zst sway-f4b882475eee7a81c206c7825616cc4656b2f60b.zip |
Merge branch 'master' into pid-workspaces
Diffstat (limited to 'sway/config/output.c')
-rw-r--r-- | sway/config/output.c | 172 |
1 files changed, 145 insertions, 27 deletions
diff --git a/sway/config/output.c b/sway/config/output.c index 648ded27..504c48c6 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -45,10 +45,6 @@ struct output_config *new_output_config(const char *name) { | |||
45 | } | 45 | } |
46 | 46 | ||
47 | void merge_output_config(struct output_config *dst, struct output_config *src) { | 47 | void merge_output_config(struct output_config *dst, struct output_config *src) { |
48 | if (src->name) { | ||
49 | free(dst->name); | ||
50 | dst->name = strdup(src->name); | ||
51 | } | ||
52 | if (src->enabled != -1) { | 48 | if (src->enabled != -1) { |
53 | dst->enabled = src->enabled; | 49 | dst->enabled = src->enabled; |
54 | } | 50 | } |
@@ -86,11 +82,61 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { | |||
86 | } | 82 | } |
87 | } | 83 | } |
88 | 84 | ||
85 | static void merge_wildcard_on_all(struct output_config *wildcard) { | ||
86 | for (int i = 0; i < config->output_configs->length; i++) { | ||
87 | struct output_config *oc = config->output_configs->items[i]; | ||
88 | if (strcmp(wildcard->name, oc->name) != 0) { | ||
89 | wlr_log(WLR_DEBUG, "Merging output * config on %s", oc->name); | ||
90 | merge_output_config(oc, wildcard); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | struct output_config *store_output_config(struct output_config *oc) { | ||
96 | bool wildcard = strcmp(oc->name, "*") == 0; | ||
97 | if (wildcard) { | ||
98 | merge_wildcard_on_all(oc); | ||
99 | } | ||
100 | |||
101 | int i = list_seq_find(config->output_configs, output_name_cmp, oc->name); | ||
102 | if (i >= 0) { | ||
103 | wlr_log(WLR_DEBUG, "Merging on top of existing output config"); | ||
104 | struct output_config *current = config->output_configs->items[i]; | ||
105 | merge_output_config(current, oc); | ||
106 | free_output_config(oc); | ||
107 | oc = current; | ||
108 | } else if (!wildcard) { | ||
109 | wlr_log(WLR_DEBUG, "Adding non-wildcard output config"); | ||
110 | i = list_seq_find(config->output_configs, output_name_cmp, "*"); | ||
111 | if (i >= 0) { | ||
112 | wlr_log(WLR_DEBUG, "Merging on top of output * config"); | ||
113 | struct output_config *current = new_output_config(oc->name); | ||
114 | merge_output_config(current, config->output_configs->items[i]); | ||
115 | merge_output_config(current, oc); | ||
116 | free_output_config(oc); | ||
117 | oc = current; | ||
118 | } | ||
119 | list_add(config->output_configs, oc); | ||
120 | } else { | ||
121 | // New wildcard config. Just add it | ||
122 | wlr_log(WLR_DEBUG, "Adding output * config"); | ||
123 | list_add(config->output_configs, oc); | ||
124 | } | ||
125 | |||
126 | wlr_log(WLR_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " | ||
127 | "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", | ||
128 | oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, | ||
129 | oc->x, oc->y, oc->scale, oc->transform, oc->background, | ||
130 | oc->background_option, oc->dpms_state); | ||
131 | |||
132 | return oc; | ||
133 | } | ||
134 | |||
89 | static void set_mode(struct wlr_output *output, int width, int height, | 135 | static void set_mode(struct wlr_output *output, int width, int height, |
90 | float refresh_rate) { | 136 | float refresh_rate) { |
91 | int mhz = (int)(refresh_rate * 1000); | 137 | int mhz = (int)(refresh_rate * 1000); |
92 | if (wl_list_empty(&output->modes)) { | 138 | if (wl_list_empty(&output->modes)) { |
93 | wlr_log(L_DEBUG, "Assigning custom mode to %s", output->name); | 139 | wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); |
94 | wlr_output_set_custom_mode(output, width, height, mhz); | 140 | wlr_output_set_custom_mode(output, width, height, mhz); |
95 | return; | 141 | return; |
96 | } | 142 | } |
@@ -106,9 +152,9 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
106 | } | 152 | } |
107 | } | 153 | } |
108 | if (!best) { | 154 | if (!best) { |
109 | wlr_log(L_ERROR, "Configured mode for %s not available", output->name); | 155 | wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name); |
110 | } else { | 156 | } else { |
111 | wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); | 157 | wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); |
112 | wlr_output_set_mode(output, best); | 158 | wlr_output_set_mode(output, best); |
113 | } | 159 | } |
114 | } | 160 | } |
@@ -116,7 +162,7 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
116 | void terminate_swaybg(pid_t pid) { | 162 | void terminate_swaybg(pid_t pid) { |
117 | int ret = kill(pid, SIGTERM); | 163 | int ret = kill(pid, SIGTERM); |
118 | if (ret != 0) { | 164 | if (ret != 0) { |
119 | wlr_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); | 165 | wlr_log(WLR_ERROR, "Unable to terminate swaybg [pid: %d]", pid); |
120 | } else { | 166 | } else { |
121 | int status; | 167 | int status; |
122 | waitpid(pid, &status, 0); | 168 | waitpid(pid, &status, 0); |
@@ -144,37 +190,27 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
144 | } | 190 | } |
145 | 191 | ||
146 | if (oc && oc->width > 0 && oc->height > 0) { | 192 | if (oc && oc->width > 0 && oc->height > 0) { |
147 | wlr_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, | 193 | wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, |
148 | oc->height, oc->refresh_rate); | 194 | oc->height, oc->refresh_rate); |
149 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); | 195 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); |
150 | } | 196 | } |
151 | if (oc && oc->scale > 0) { | 197 | if (oc && oc->scale > 0) { |
152 | wlr_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); | 198 | wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); |
153 | wlr_output_set_scale(wlr_output, oc->scale); | 199 | wlr_output_set_scale(wlr_output, oc->scale); |
154 | } | 200 | } |
155 | if (oc && oc->transform >= 0) { | 201 | if (oc && oc->transform >= 0) { |
156 | wlr_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); | 202 | wlr_log(WLR_DEBUG, "Set %s transform to %d", oc->name, oc->transform); |
157 | wlr_output_set_transform(wlr_output, oc->transform); | 203 | wlr_output_set_transform(wlr_output, oc->transform); |
158 | } | 204 | } |
159 | 205 | ||
160 | // Find position for it | 206 | // Find position for it |
161 | if (oc && (oc->x != -1 || oc->y != -1)) { | 207 | if (oc && (oc->x != -1 || oc->y != -1)) { |
162 | wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); | 208 | wlr_log(WLR_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); |
163 | wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); | 209 | wlr_output_layout_add(output_layout, wlr_output, oc->x, oc->y); |
164 | } else { | 210 | } else { |
165 | wlr_output_layout_add_auto(output_layout, wlr_output); | 211 | wlr_output_layout_add_auto(output_layout, wlr_output); |
166 | } | 212 | } |
167 | 213 | ||
168 | if (!oc || !oc->background) { | ||
169 | // Look for a * config for background | ||
170 | int i = list_seq_find(config->output_configs, output_name_cmp, "*"); | ||
171 | if (i >= 0) { | ||
172 | oc = config->output_configs->items[i]; | ||
173 | } else { | ||
174 | oc = NULL; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | int output_i; | 214 | int output_i; |
179 | for (output_i = 0; output_i < root_container.children->length; ++output_i) { | 215 | for (output_i = 0; output_i < root_container.children->length; ++output_i) { |
180 | if (root_container.children->items[output_i] == output) { | 216 | if (root_container.children->items[output_i] == output) { |
@@ -187,7 +223,7 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
187 | terminate_swaybg(output->sway_output->bg_pid); | 223 | terminate_swaybg(output->sway_output->bg_pid); |
188 | } | 224 | } |
189 | 225 | ||
190 | wlr_log(L_DEBUG, "Setting background for output %d to %s", | 226 | wlr_log(WLR_DEBUG, "Setting background for output %d to %s", |
191 | output_i, oc->background); | 227 | output_i, oc->background); |
192 | 228 | ||
193 | size_t len = snprintf(NULL, 0, "%s %d %s %s", | 229 | size_t len = snprintf(NULL, 0, "%s %d %s %s", |
@@ -195,28 +231,30 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
195 | output_i, oc->background, oc->background_option); | 231 | output_i, oc->background, oc->background_option); |
196 | char *command = malloc(len + 1); | 232 | char *command = malloc(len + 1); |
197 | if (!command) { | 233 | if (!command) { |
198 | wlr_log(L_DEBUG, "Unable to allocate swaybg command"); | 234 | wlr_log(WLR_DEBUG, "Unable to allocate swaybg command"); |
199 | return; | 235 | return; |
200 | } | 236 | } |
201 | snprintf(command, len + 1, "%s %d %s %s", | 237 | snprintf(command, len + 1, "%s %d %s %s", |
202 | config->swaybg_command ? config->swaybg_command : "swaybg", | 238 | config->swaybg_command ? config->swaybg_command : "swaybg", |
203 | output_i, oc->background, oc->background_option); | 239 | output_i, oc->background, oc->background_option); |
204 | wlr_log(L_DEBUG, "-> %s", command); | 240 | wlr_log(WLR_DEBUG, "-> %s", command); |
205 | 241 | ||
206 | char *const cmd[] = { "sh", "-c", command, NULL }; | 242 | char *const cmd[] = { "sh", "-c", command, NULL }; |
207 | output->sway_output->bg_pid = fork(); | 243 | output->sway_output->bg_pid = fork(); |
208 | if (output->sway_output->bg_pid == 0) { | 244 | if (output->sway_output->bg_pid == 0) { |
209 | execvp(cmd[0], cmd); | 245 | execvp(cmd[0], cmd); |
246 | } else { | ||
247 | free(command); | ||
210 | } | 248 | } |
211 | } | 249 | } |
212 | if (oc && oc->dpms_state != DPMS_IGNORE) { | 250 | if (oc && oc->dpms_state != DPMS_IGNORE) { |
213 | switch (oc->dpms_state) { | 251 | switch (oc->dpms_state) { |
214 | case DPMS_ON: | 252 | case DPMS_ON: |
215 | wlr_log(L_DEBUG, "Turning on screen"); | 253 | wlr_log(WLR_DEBUG, "Turning on screen"); |
216 | wlr_output_enable(wlr_output, true); | 254 | wlr_output_enable(wlr_output, true); |
217 | break; | 255 | break; |
218 | case DPMS_OFF: | 256 | case DPMS_OFF: |
219 | wlr_log(L_DEBUG, "Turning off screen"); | 257 | wlr_log(WLR_DEBUG, "Turning off screen"); |
220 | wlr_output_enable(wlr_output, false); | 258 | wlr_output_enable(wlr_output, false); |
221 | break; | 259 | break; |
222 | case DPMS_IGNORE: | 260 | case DPMS_IGNORE: |
@@ -225,6 +263,60 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
225 | } | 263 | } |
226 | } | 264 | } |
227 | 265 | ||
266 | static struct output_config *get_output_config(char *name, char *identifier) { | ||
267 | int i = list_seq_find(config->output_configs, output_name_cmp, name); | ||
268 | if (i >= 0) { | ||
269 | return config->output_configs->items[i]; | ||
270 | } | ||
271 | |||
272 | i = list_seq_find(config->output_configs, output_name_cmp, identifier); | ||
273 | if (i >= 0) { | ||
274 | return config->output_configs->items[i]; | ||
275 | } | ||
276 | |||
277 | return NULL; | ||
278 | } | ||
279 | |||
280 | void apply_output_config_to_outputs(struct output_config *oc) { | ||
281 | // Try to find the output container and apply configuration now. If | ||
282 | // this is during startup then there will be no container and config | ||
283 | // will be applied during normal "new output" event from wlroots. | ||
284 | bool wildcard = strcmp(oc->name, "*") == 0; | ||
285 | char id[128]; | ||
286 | struct sway_output *sway_output; | ||
287 | wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) { | ||
288 | char *name = sway_output->wlr_output->name; | ||
289 | output_get_identifier(id, sizeof(id), sway_output); | ||
290 | if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) { | ||
291 | if (!sway_output->swayc) { | ||
292 | if (!oc->enabled) { | ||
293 | if (!wildcard) { | ||
294 | break; | ||
295 | } | ||
296 | continue; | ||
297 | } | ||
298 | |||
299 | output_enable(sway_output); | ||
300 | } | ||
301 | |||
302 | struct output_config *current = oc; | ||
303 | if (wildcard) { | ||
304 | struct output_config *tmp = get_output_config(name, id); | ||
305 | if (tmp) { | ||
306 | current = tmp; | ||
307 | } | ||
308 | } | ||
309 | apply_output_config(current, sway_output->swayc); | ||
310 | |||
311 | if (!wildcard) { | ||
312 | // Stop looking if the output config isn't applicable to all | ||
313 | // outputs | ||
314 | break; | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | |||
228 | void free_output_config(struct output_config *oc) { | 320 | void free_output_config(struct output_config *oc) { |
229 | if (!oc) { | 321 | if (!oc) { |
230 | return; | 322 | return; |
@@ -234,3 +326,29 @@ void free_output_config(struct output_config *oc) { | |||
234 | free(oc->background_option); | 326 | free(oc->background_option); |
235 | free(oc); | 327 | free(oc); |
236 | } | 328 | } |
329 | |||
330 | static void default_output_config(struct output_config *oc, | ||
331 | struct wlr_output *wlr_output) { | ||
332 | oc->enabled = 1; | ||
333 | if (!wl_list_empty(&wlr_output->modes)) { | ||
334 | struct wlr_output_mode *mode = | ||
335 | wl_container_of(wlr_output->modes.prev, mode, link); | ||
336 | oc->width = mode->width; | ||
337 | oc->height = mode->height; | ||
338 | oc->refresh_rate = mode->refresh; | ||
339 | } | ||
340 | oc->x = oc->y = -1; | ||
341 | oc->scale = 1; | ||
342 | oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||
343 | } | ||
344 | |||
345 | void create_default_output_configs(void) { | ||
346 | struct sway_output *sway_output; | ||
347 | wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) { | ||
348 | char *name = sway_output->wlr_output->name; | ||
349 | struct output_config *oc = new_output_config(name); | ||
350 | default_output_config(oc, sway_output->wlr_output); | ||
351 | list_add(config->output_configs, oc); | ||
352 | } | ||
353 | } | ||
354 | |||