diff options
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | include/sway/output.h | 4 | ||||
-rw-r--r-- | sway/commands/output/background.c | 18 | ||||
-rw-r--r-- | sway/config/output.c | 38 | ||||
-rw-r--r-- | sway/desktop/output.c | 62 | ||||
-rw-r--r-- | sway/tree/output.c | 27 |
6 files changed, 89 insertions, 62 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index 978606a6..8215ff59 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -568,7 +568,7 @@ struct output_config *new_output_config(const char *name); | |||
568 | 568 | ||
569 | void merge_output_config(struct output_config *dst, struct output_config *src); | 569 | void merge_output_config(struct output_config *dst, struct output_config *src); |
570 | 570 | ||
571 | void apply_output_config(struct output_config *oc, struct sway_output *output); | 571 | bool apply_output_config(struct output_config *oc, struct sway_output *output); |
572 | 572 | ||
573 | struct output_config *store_output_config(struct output_config *oc); | 573 | struct output_config *store_output_config(struct output_config *oc); |
574 | 574 | ||
diff --git a/include/sway/output.h b/include/sway/output.h index bdf9614d..9ebdb6c1 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -31,7 +31,7 @@ struct sway_output { | |||
31 | int lx, ly; | 31 | int lx, ly; |
32 | int width, height; | 32 | int width, height; |
33 | 33 | ||
34 | bool enabled; | 34 | bool enabled, configured; |
35 | list_t *workspaces; | 35 | list_t *workspaces; |
36 | 36 | ||
37 | struct sway_output_state current; | 37 | struct sway_output_state current; |
@@ -144,8 +144,6 @@ void output_get_box(struct sway_output *output, struct wlr_box *box); | |||
144 | enum sway_container_layout output_get_default_layout( | 144 | enum sway_container_layout output_get_default_layout( |
145 | struct sway_output *output); | 145 | struct sway_output *output); |
146 | 146 | ||
147 | void output_add_listeners(struct sway_output *output); | ||
148 | |||
149 | void render_rect(struct wlr_output *wlr_output, | 147 | void render_rect(struct wlr_output *wlr_output, |
150 | pixman_region32_t *output_damage, const struct wlr_box *_box, | 148 | pixman_region32_t *output_damage, const struct wlr_box *_box, |
151 | float color[static 4]); | 149 | float color[static 4]); |
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index ae2f0640..00038e67 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c | |||
@@ -34,8 +34,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
34 | struct output_config *output = config->handler_context.output_config; | 34 | struct output_config *output = config->handler_context.output_config; |
35 | 35 | ||
36 | if (strcasecmp(argv[1], "solid_color") == 0) { | 36 | if (strcasecmp(argv[1], "solid_color") == 0) { |
37 | output->background = calloc(1, strlen(argv[0]) + 3); | 37 | output->background = strdup(argv[0]); |
38 | snprintf(output->background, strlen(argv[0]) + 3, "\"%s\"", argv[0]); | ||
39 | output->background_option = strdup("solid_color"); | 38 | output->background_option = strdup("solid_color"); |
40 | output->background_fallback = NULL; | 39 | output->background_fallback = NULL; |
41 | argc -= 2; argv += 2; | 40 | argc -= 2; argv += 2; |
@@ -119,16 +118,6 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
119 | src); | 118 | src); |
120 | free(src); | 119 | free(src); |
121 | } else { | 120 | } else { |
122 | // Escape double quotes in the final path for swaybg | ||
123 | for (size_t i = 0; i < strlen(src); i++) { | ||
124 | if (src[i] == '"') { | ||
125 | src = realloc(src, strlen(src) + 2); | ||
126 | memmove(src + i + 1, src + i, strlen(src + i) + 1); | ||
127 | *(src + i) = '\\'; | ||
128 | i++; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | output->background = src; | 121 | output->background = src; |
133 | output->background_option = strdup(mode); | 122 | output->background_option = strdup(mode); |
134 | } | 123 | } |
@@ -136,9 +125,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
136 | 125 | ||
137 | output->background_fallback = NULL; | 126 | output->background_fallback = NULL; |
138 | if (argc && *argv[0] == '#') { | 127 | if (argc && *argv[0] == '#') { |
139 | output->background_fallback = calloc(1, strlen(argv[0]) + 3); | 128 | output->background_fallback = strdup(argv[0]); |
140 | snprintf(output->background_fallback, strlen(argv[0]) + 3, | ||
141 | "\"%s\"", argv[0]); | ||
142 | argc--; argv++; | 129 | argc--; argv++; |
143 | 130 | ||
144 | if (!can_access) { | 131 | if (!can_access) { |
@@ -153,4 +140,3 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { | |||
153 | config->handler_context.leftovers.argv = argv; | 140 | config->handler_context.leftovers.argv = argv; |
154 | return NULL; | 141 | return NULL; |
155 | } | 142 | } |
156 | |||
diff --git a/sway/config/output.c b/sway/config/output.c index f23d316d..6e504751 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -137,13 +137,12 @@ struct output_config *store_output_config(struct output_config *oc) { | |||
137 | return oc; | 137 | return oc; |
138 | } | 138 | } |
139 | 139 | ||
140 | static void set_mode(struct wlr_output *output, int width, int height, | 140 | static bool set_mode(struct wlr_output *output, int width, int height, |
141 | float refresh_rate) { | 141 | float refresh_rate) { |
142 | int mhz = (int)(refresh_rate * 1000); | 142 | int mhz = (int)(refresh_rate * 1000); |
143 | if (wl_list_empty(&output->modes)) { | 143 | if (wl_list_empty(&output->modes)) { |
144 | wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); | 144 | wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); |
145 | wlr_output_set_custom_mode(output, width, height, mhz); | 145 | return wlr_output_set_custom_mode(output, width, height, mhz); |
146 | return; | ||
147 | } | 146 | } |
148 | 147 | ||
149 | struct wlr_output_mode *mode, *best = NULL; | 148 | struct wlr_output_mode *mode, *best = NULL; |
@@ -158,10 +157,12 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
158 | } | 157 | } |
159 | if (!best) { | 158 | if (!best) { |
160 | wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name); | 159 | wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name); |
160 | wlr_log(WLR_INFO, "Picking default mode instead"); | ||
161 | best = wl_container_of(output->modes.prev, mode, link); | ||
161 | } else { | 162 | } else { |
162 | wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); | 163 | wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); |
163 | wlr_output_set_mode(output, best); | ||
164 | } | 164 | } |
165 | return wlr_output_set_mode(output, best); | ||
165 | } | 166 | } |
166 | 167 | ||
167 | void terminate_swaybg(pid_t pid) { | 168 | void terminate_swaybg(pid_t pid) { |
@@ -174,33 +175,48 @@ void terminate_swaybg(pid_t pid) { | |||
174 | } | 175 | } |
175 | } | 176 | } |
176 | 177 | ||
177 | void apply_output_config(struct output_config *oc, struct sway_output *output) { | 178 | bool apply_output_config(struct output_config *oc, struct sway_output *output) { |
178 | struct wlr_output *wlr_output = output->wlr_output; | 179 | struct wlr_output *wlr_output = output->wlr_output; |
179 | 180 | ||
180 | if (oc && oc->enabled == 0) { | 181 | if (oc && !oc->enabled) { |
182 | // Output is configured to be disabled | ||
181 | if (output->enabled) { | 183 | if (output->enabled) { |
182 | output_disable(output); | 184 | output_disable(output); |
183 | wlr_output_layout_remove(root->output_layout, wlr_output); | 185 | wlr_output_layout_remove(root->output_layout, wlr_output); |
184 | } | 186 | } |
185 | wlr_output_enable(wlr_output, false); | 187 | wlr_output_enable(wlr_output, false); |
186 | return; | 188 | return true; |
187 | } else if (!output->enabled) { | 189 | } else if (!output->enabled) { |
190 | // Output is not enabled. Enable it, output_enable will call us again. | ||
188 | if (!oc || oc->dpms_state != DPMS_OFF) { | 191 | if (!oc || oc->dpms_state != DPMS_OFF) { |
189 | wlr_output_enable(wlr_output, true); | 192 | wlr_output_enable(wlr_output, true); |
190 | } | 193 | } |
191 | output_enable(output, oc); | 194 | output_enable(output, oc); |
192 | return; | 195 | return true; |
193 | } | 196 | } |
194 | 197 | ||
198 | bool modeset_success; | ||
195 | if (oc && oc->width > 0 && oc->height > 0) { | 199 | if (oc && oc->width > 0 && oc->height > 0) { |
196 | wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, | 200 | wlr_log(WLR_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, |
197 | oc->height, oc->refresh_rate); | 201 | oc->height, oc->refresh_rate); |
198 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); | 202 | modeset_success = |
203 | set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); | ||
199 | } else if (!wl_list_empty(&wlr_output->modes)) { | 204 | } else if (!wl_list_empty(&wlr_output->modes)) { |
200 | struct wlr_output_mode *mode = | 205 | struct wlr_output_mode *mode = |
201 | wl_container_of(wlr_output->modes.prev, mode, link); | 206 | wl_container_of(wlr_output->modes.prev, mode, link); |
202 | wlr_output_set_mode(wlr_output, mode); | 207 | modeset_success = wlr_output_set_mode(wlr_output, mode); |
208 | } else { | ||
209 | // Output doesn't support modes | ||
210 | modeset_success = true; | ||
203 | } | 211 | } |
212 | if (!modeset_success) { | ||
213 | // Failed to modeset, maybe the output is missing a CRTC. Leave the | ||
214 | // output disabled for now and try again when the output gets the mode | ||
215 | // we asked for. | ||
216 | wlr_log(WLR_ERROR, "Failed to modeset output %s", wlr_output->name); | ||
217 | return false; | ||
218 | } | ||
219 | |||
204 | if (oc && oc->scale > 0) { | 220 | if (oc && oc->scale > 0) { |
205 | wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); | 221 | wlr_log(WLR_DEBUG, "Set %s scale to %f", oc->name, oc->scale); |
206 | wlr_output_set_scale(wlr_output, oc->scale); | 222 | wlr_output_set_scale(wlr_output, oc->scale); |
@@ -264,6 +280,8 @@ void apply_output_config(struct output_config *oc, struct sway_output *output) { | |||
264 | break; | 280 | break; |
265 | } | 281 | } |
266 | } | 282 | } |
283 | |||
284 | return true; | ||
267 | } | 285 | } |
268 | 286 | ||
269 | static void default_output_config(struct output_config *oc, | 287 | static void default_output_config(struct output_config *oc, |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 04c9b4f6..37651d66 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -359,8 +359,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
359 | static void damage_handle_frame(struct wl_listener *listener, void *data) { | 359 | static void damage_handle_frame(struct wl_listener *listener, void *data) { |
360 | struct sway_output *output = | 360 | struct sway_output *output = |
361 | wl_container_of(listener, output, damage_frame); | 361 | wl_container_of(listener, output, damage_frame); |
362 | 362 | if (!output->enabled || !output->wlr_output->enabled) { | |
363 | if (!output->wlr_output->enabled) { | ||
364 | return; | 363 | return; |
365 | } | 364 | } |
366 | 365 | ||
@@ -475,6 +474,9 @@ void output_damage_whole_container(struct sway_output *output, | |||
475 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 474 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { |
476 | struct sway_output *output = | 475 | struct sway_output *output = |
477 | wl_container_of(listener, output, damage_destroy); | 476 | wl_container_of(listener, output, damage_destroy); |
477 | if (!output->enabled) { | ||
478 | return; | ||
479 | } | ||
478 | output_disable(output); | 480 | output_disable(output); |
479 | transaction_commit_dirty(); | 481 | transaction_commit_dirty(); |
480 | } | 482 | } |
@@ -488,11 +490,33 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
488 | } | 490 | } |
489 | output_begin_destroy(output); | 491 | output_begin_destroy(output); |
490 | 492 | ||
493 | wl_list_remove(&output->destroy.link); | ||
494 | wl_list_remove(&output->mode.link); | ||
495 | wl_list_remove(&output->transform.link); | ||
496 | wl_list_remove(&output->scale.link); | ||
497 | wl_list_remove(&output->present.link); | ||
498 | wl_list_remove(&output->damage_destroy.link); | ||
499 | wl_list_remove(&output->damage_frame.link); | ||
500 | |||
491 | transaction_commit_dirty(); | 501 | transaction_commit_dirty(); |
492 | } | 502 | } |
493 | 503 | ||
494 | static void handle_mode(struct wl_listener *listener, void *data) { | 504 | static void handle_mode(struct wl_listener *listener, void *data) { |
495 | struct sway_output *output = wl_container_of(listener, output, mode); | 505 | struct sway_output *output = wl_container_of(listener, output, mode); |
506 | if (!output->configured) { | ||
507 | return; | ||
508 | } | ||
509 | if (!output->enabled) { | ||
510 | struct output_config *oc = output_find_config(output); | ||
511 | if (output->wlr_output->current_mode != NULL && | ||
512 | (!oc || oc->enabled)) { | ||
513 | // We want to enable this output, but it didn't work last time, | ||
514 | // possibly because we hadn't enough CRTCs. Try again now that the | ||
515 | // output has a mode. | ||
516 | output_enable(output, oc); | ||
517 | } | ||
518 | return; | ||
519 | } | ||
496 | arrange_layers(output); | 520 | arrange_layers(output); |
497 | arrange_output(output); | 521 | arrange_output(output); |
498 | transaction_commit_dirty(); | 522 | transaction_commit_dirty(); |
@@ -500,6 +524,9 @@ static void handle_mode(struct wl_listener *listener, void *data) { | |||
500 | 524 | ||
501 | static void handle_transform(struct wl_listener *listener, void *data) { | 525 | static void handle_transform(struct wl_listener *listener, void *data) { |
502 | struct sway_output *output = wl_container_of(listener, output, transform); | 526 | struct sway_output *output = wl_container_of(listener, output, transform); |
527 | if (!output->enabled) { | ||
528 | return; | ||
529 | } | ||
503 | arrange_layers(output); | 530 | arrange_layers(output); |
504 | arrange_output(output); | 531 | arrange_output(output); |
505 | transaction_commit_dirty(); | 532 | transaction_commit_dirty(); |
@@ -512,6 +539,9 @@ static void update_textures(struct sway_container *con, void *data) { | |||
512 | 539 | ||
513 | static void handle_scale(struct wl_listener *listener, void *data) { | 540 | static void handle_scale(struct wl_listener *listener, void *data) { |
514 | struct sway_output *output = wl_container_of(listener, output, scale); | 541 | struct sway_output *output = wl_container_of(listener, output, scale); |
542 | if (!output->enabled) { | ||
543 | return; | ||
544 | } | ||
515 | arrange_layers(output); | 545 | arrange_layers(output); |
516 | output_for_each_container(output, update_textures, NULL); | 546 | output_for_each_container(output, update_textures, NULL); |
517 | arrange_output(output); | 547 | arrange_output(output); |
@@ -530,6 +560,10 @@ static void handle_present(struct wl_listener *listener, void *data) { | |||
530 | struct sway_output *output = wl_container_of(listener, output, present); | 560 | struct sway_output *output = wl_container_of(listener, output, present); |
531 | struct wlr_output_event_present *output_event = data; | 561 | struct wlr_output_event_present *output_event = data; |
532 | 562 | ||
563 | if (!output->enabled) { | ||
564 | return; | ||
565 | } | ||
566 | |||
533 | struct wlr_presentation_event event = { | 567 | struct wlr_presentation_event event = { |
534 | .output = output->wlr_output, | 568 | .output = output->wlr_output, |
535 | .tv_sec = (uint64_t)output_event->when->tv_sec, | 569 | .tv_sec = (uint64_t)output_event->when->tv_sec, |
@@ -552,10 +586,23 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
552 | } | 586 | } |
553 | output->server = server; | 587 | output->server = server; |
554 | output->damage = wlr_output_damage_create(wlr_output); | 588 | output->damage = wlr_output_damage_create(wlr_output); |
589 | |||
590 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
555 | output->destroy.notify = handle_destroy; | 591 | output->destroy.notify = handle_destroy; |
592 | wl_signal_add(&wlr_output->events.mode, &output->mode); | ||
593 | output->mode.notify = handle_mode; | ||
594 | wl_signal_add(&wlr_output->events.transform, &output->transform); | ||
595 | output->transform.notify = handle_transform; | ||
596 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
597 | output->scale.notify = handle_scale; | ||
598 | wl_signal_add(&wlr_output->events.present, &output->present); | ||
599 | output->present.notify = handle_present; | ||
600 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | ||
601 | output->damage_frame.notify = damage_handle_frame; | ||
602 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | ||
603 | output->damage_destroy.notify = damage_handle_destroy; | ||
556 | 604 | ||
557 | struct output_config *oc = output_find_config(output); | 605 | struct output_config *oc = output_find_config(output); |
558 | |||
559 | if (!oc || oc->enabled) { | 606 | if (!oc || oc->enabled) { |
560 | output_enable(output, oc); | 607 | output_enable(output, oc); |
561 | } else { | 608 | } else { |
@@ -564,12 +611,3 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
564 | 611 | ||
565 | transaction_commit_dirty(); | 612 | transaction_commit_dirty(); |
566 | } | 613 | } |
567 | |||
568 | void output_add_listeners(struct sway_output *output) { | ||
569 | output->mode.notify = handle_mode; | ||
570 | output->transform.notify = handle_transform; | ||
571 | output->scale.notify = handle_scale; | ||
572 | output->present.notify = handle_present; | ||
573 | output->damage_frame.notify = damage_handle_frame; | ||
574 | output->damage_destroy.notify = damage_handle_destroy; | ||
575 | } | ||
diff --git a/sway/tree/output.c b/sway/tree/output.c index f24be010..b79e70d4 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -57,7 +57,6 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { | |||
57 | output->wlr_output = wlr_output; | 57 | output->wlr_output = wlr_output; |
58 | wlr_output->data = output; | 58 | wlr_output->data = output; |
59 | 59 | ||
60 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
61 | wl_signal_init(&output->events.destroy); | 60 | wl_signal_init(&output->events.destroy); |
62 | 61 | ||
63 | wl_list_insert(&root->all_outputs, &output->link); | 62 | wl_list_insert(&root->all_outputs, &output->link); |
@@ -79,6 +78,12 @@ void output_enable(struct sway_output *output, struct output_config *oc) { | |||
79 | } | 78 | } |
80 | 79 | ||
81 | output->enabled = true; | 80 | output->enabled = true; |
81 | if (!apply_output_config(oc, output)) { | ||
82 | output->enabled = false; | ||
83 | return; | ||
84 | } | ||
85 | |||
86 | output->configured = true; | ||
82 | list_add(root->outputs, output); | 87 | list_add(root->outputs, output); |
83 | 88 | ||
84 | output->lx = wlr_output->lx; | 89 | output->lx = wlr_output->lx; |
@@ -105,8 +110,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) { | |||
105 | ipc_event_workspace(NULL, ws, "init"); | 110 | ipc_event_workspace(NULL, ws, "init"); |
106 | } | 111 | } |
107 | 112 | ||
108 | apply_output_config(oc, output); | ||
109 | |||
110 | if (ws && config->default_orientation == L_NONE) { | 113 | if (ws && config->default_orientation == L_NONE) { |
111 | // Since the output transformation and resolution could have changed | 114 | // Since the output transformation and resolution could have changed |
112 | // due to applying the output config, the previously set layout for the | 115 | // due to applying the output config, the previously set layout for the |
@@ -116,15 +119,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) { | |||
116 | 119 | ||
117 | input_manager_configure_xcursor(); | 120 | input_manager_configure_xcursor(); |
118 | 121 | ||
119 | wl_signal_add(&wlr_output->events.mode, &output->mode); | ||
120 | wl_signal_add(&wlr_output->events.transform, &output->transform); | ||
121 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
122 | wl_signal_add(&wlr_output->events.present, &output->present); | ||
123 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | ||
124 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | ||
125 | |||
126 | output_add_listeners(output); | ||
127 | |||
128 | wl_signal_emit(&root->events.new_node, &output->node); | 122 | wl_signal_emit(&root->events.new_node, &output->node); |
129 | 123 | ||
130 | arrange_layers(output); | 124 | arrange_layers(output); |
@@ -233,14 +227,8 @@ void output_disable(struct sway_output *output) { | |||
233 | int index = list_find(root->outputs, output); | 227 | int index = list_find(root->outputs, output); |
234 | list_del(root->outputs, index); | 228 | list_del(root->outputs, index); |
235 | 229 | ||
236 | wl_list_remove(&output->mode.link); | ||
237 | wl_list_remove(&output->transform.link); | ||
238 | wl_list_remove(&output->scale.link); | ||
239 | wl_list_remove(&output->present.link); | ||
240 | wl_list_remove(&output->damage_destroy.link); | ||
241 | wl_list_remove(&output->damage_frame.link); | ||
242 | |||
243 | output->enabled = false; | 230 | output->enabled = false; |
231 | output->configured = false; | ||
244 | 232 | ||
245 | arrange_root(); | 233 | arrange_root(); |
246 | } | 234 | } |
@@ -255,7 +243,6 @@ void output_begin_destroy(struct sway_output *output) { | |||
255 | node_set_dirty(&output->node); | 243 | node_set_dirty(&output->node); |
256 | 244 | ||
257 | wl_list_remove(&output->link); | 245 | wl_list_remove(&output->link); |
258 | wl_list_remove(&output->destroy.link); | ||
259 | output->wlr_output->data = NULL; | 246 | output->wlr_output->data = NULL; |
260 | output->wlr_output = NULL; | 247 | output->wlr_output = NULL; |
261 | } | 248 | } |