aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h2
-rw-r--r--include/sway/output.h4
-rw-r--r--sway/commands/output/background.c18
-rw-r--r--sway/config/output.c38
-rw-r--r--sway/desktop/output.c62
-rw-r--r--sway/tree/output.c27
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
569void merge_output_config(struct output_config *dst, struct output_config *src); 569void merge_output_config(struct output_config *dst, struct output_config *src);
570 570
571void apply_output_config(struct output_config *oc, struct sway_output *output); 571bool apply_output_config(struct output_config *oc, struct sway_output *output);
572 572
573struct output_config *store_output_config(struct output_config *oc); 573struct 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);
144enum sway_container_layout output_get_default_layout( 144enum sway_container_layout output_get_default_layout(
145 struct sway_output *output); 145 struct sway_output *output);
146 146
147void output_add_listeners(struct sway_output *output);
148
149void render_rect(struct wlr_output *wlr_output, 147void 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
140static void set_mode(struct wlr_output *output, int width, int height, 140static 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
167void terminate_swaybg(pid_t pid) { 168void terminate_swaybg(pid_t pid) {
@@ -174,33 +175,48 @@ void terminate_swaybg(pid_t pid) {
174 } 175 }
175} 176}
176 177
177void apply_output_config(struct output_config *oc, struct sway_output *output) { 178bool 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
269static void default_output_config(struct output_config *oc, 287static 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) {
359static void damage_handle_frame(struct wl_listener *listener, void *data) { 359static 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,
475static void damage_handle_destroy(struct wl_listener *listener, void *data) { 474static 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
494static void handle_mode(struct wl_listener *listener, void *data) { 504static 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
501static void handle_transform(struct wl_listener *listener, void *data) { 525static 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
513static void handle_scale(struct wl_listener *listener, void *data) { 540static 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
568void 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}