aboutsummaryrefslogtreecommitdiffstats
path: root/sway/config/output.c
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 /sway/config/output.c
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.
Diffstat (limited to 'sway/config/output.c')
-rw-r--r--sway/config/output.c38
1 files changed, 28 insertions, 10 deletions
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,