aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2019-01-17 22:30:24 +0100
committerLibravatar emersion <contact@emersion.fr>2019-01-18 10:09:10 +0100
commita737d7ecc4d7f4825ca7879e3449522bc87049be (patch)
tree7c40fbaebce93738d1f44d32f2d6f059a073e85e
parentoutput: remove output_add_listeners (diff)
downloadsway-a737d7ecc4d7f4825ca7879e3449522bc87049be.tar.gz
sway-a737d7ecc4d7f4825ca7879e3449522bc87049be.tar.zst
sway-a737d7ecc4d7f4825ca7879e3449522bc87049be.zip
Better handle outputs without CRTC
This happens if you plug in more outputs than supported by your GPU. This patch makes it so outputs without CRTCs appear as disabled. As soon as they get a CRTC (signalled via the mode event), we can enable them.
-rw-r--r--include/sway/config.h2
-rw-r--r--include/sway/output.h2
-rw-r--r--sway/config/output.c38
-rw-r--r--sway/desktop/output.c12
-rw-r--r--sway/tree/output.c8
5 files changed, 47 insertions, 15 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 7279187d..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;
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 3f6c3d87..37651d66 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -503,7 +503,18 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
503 503
504static void handle_mode(struct wl_listener *listener, void *data) { 504static void handle_mode(struct wl_listener *listener, void *data) {
505 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 }
506 if (!output->enabled) { 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 }
507 return; 518 return;
508 } 519 }
509 arrange_layers(output); 520 arrange_layers(output);
@@ -592,7 +603,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
592 output->damage_destroy.notify = damage_handle_destroy; 603 output->damage_destroy.notify = damage_handle_destroy;
593 604
594 struct output_config *oc = output_find_config(output); 605 struct output_config *oc = output_find_config(output);
595
596 if (!oc || oc->enabled) { 606 if (!oc || oc->enabled) {
597 output_enable(output, oc); 607 output_enable(output, oc);
598 } else { 608 } else {
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 3c376c6b..21beb504 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -78,6 +78,12 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
78 } 78 }
79 79
80 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;
81 list_add(root->outputs, output); 87 list_add(root->outputs, output);
82 88
83 output->lx = wlr_output->lx; 89 output->lx = wlr_output->lx;
@@ -104,8 +110,6 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
104 ipc_event_workspace(NULL, ws, "init"); 110 ipc_event_workspace(NULL, ws, "init");
105 } 111 }
106 112
107 apply_output_config(oc, output);
108
109 if (ws && config->default_orientation == L_NONE) { 113 if (ws && config->default_orientation == L_NONE) {
110 // Since the output transformation and resolution could have changed 114 // Since the output transformation and resolution could have changed
111 // 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