This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository enlightenment.
View the commit online.
commit e9b6ec19f909147452efbac2a8a6604a38d7bd20
Author: [email protected] <[email protected]>
AuthorDate: Sat Mar 7 20:44:38 2026 -0700
fix: shrink X virtual screen on monitor disconnect
X RandR refuses to shrink the virtual screen (BadMatch) while any CRTC
has a panning area set, even on disabled CRTCs with stale panning from
a previous configuration. This left the virtual screen at the old
multi-monitor size after unplugging a display, causing the compositor
to render a much larger canvas than needed and severe GPU-bound slowness.
Fix by reordering panning operations:
1. Clear panning on all CRTCs before configuring outputs
2. Configure CRTCs (enable/disable as needed)
3. Release X grab and sync so CRTC changes take effect
4. Resize the virtual screen to the new layout size
5. Restore panning on active CRTCs after the resize
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
src/bin/e_comp_x_randr.c | 55 +++++++++++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 17 deletions(-)
diff --git a/src/bin/e_comp_x_randr.c b/src/bin/e_comp_x_randr.c
index 635878118..c414e7e0c 100644
--- a/src/bin/e_comp_x_randr.c
+++ b/src/bin/e_comp_x_randr.c
@@ -728,7 +728,7 @@ _e_comp_xrandr_ecore_x(void)
int minw, minh, maxw, maxh, nw, nh, pw, ph, ww, hh;
Ecore_X_Randr_Crtc *crtcs = NULL;
Ecore_X_Randr_Output *outputs = NULL, out, *outconf;
- E_Randr2_Screen **screenconf;
+ E_Randr2_Screen **screenconf = NULL;
int crtcs_num = 0, outputs_num = 0, i, numout;
Ecore_X_Randr_Crtc_Info *info;
int top_priority = 0;
@@ -766,6 +766,15 @@ _e_comp_xrandr_ecore_x(void)
crtcs = ecore_x_randr_crtcs_get(root, &crtcs_num);
outputs = ecore_x_randr_outputs_get(root, &outputs_num);
+ // clear panning on all CRTCs upfront. old panning areas from the
+ // previous configuration persist even after a CRTC is disabled and
+ // prevent X from shrinking the virtual screen later.
+ if (crtcs)
+ {
+ for (i = 0; i < crtcs_num; i++)
+ ecore_x_randr_crtc_panning_area_set(root, crtcs[i], 0, 0, 0, 0);
+ }
+
printf("RRR: crtcs=%p outputs=%p\n", crtcs, outputs);
if ((crtcs) && (outputs))
{
@@ -869,12 +878,9 @@ _e_comp_xrandr_ecore_x(void)
(screenconf[i]->config.geom.w / 2);
py = screenconf[i]->config.geom.y +
(screenconf[i]->config.geom.h / 2);
- ecore_x_randr_crtc_panning_area_set
- (root, crtcs[i],
- screenconf[i]->config.geom.x,
- screenconf[i]->config.geom.y,
- screenconf[i]->config.geom.w,
- screenconf[i]->config.geom.h);
+ // panning is set after the virtual screen resize
+ // below, because X refuses to shrink the screen while
+ // any CRTC has a panning area set.
if (screenconf[i]->config.priority == top_priority)
{
ecore_x_randr_primary_output_set(root, outconf[i]);
@@ -908,22 +914,37 @@ _e_comp_xrandr_ecore_x(void)
ecore_x_pointer_warp(root, px, py);
}
free(outputs);
- free(crtcs);
+ // release grab and sync so CRTC changes take effect before resize
+ ecore_x_ungrab();
+ ecore_x_sync();
+
+ // shrink the virtual screen to match the new layout.
+ // no panning areas are set yet (they're deferred to after resize)
+ // so X should be able to shrink without BadMatch.
printf("RRR: set vsize2: %ix%i\n", nw, nh);
ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1);
+ ecore_x_sync();
+
+ // now set panning on active CRTCs after the resize is done
+ if (crtcs)
{
- int dww = 0, dhh = 0, dww2 = 0, dhh2 = 0;
- ecore_x_randr_screen_current_size_get(root, &dww, &dhh, &dww2, &dhh2);
- printf("RRR: cur size: %ix%i\n", dww, dhh);
-// ecore_x_randr_screen_reset(root);
-// ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1);
-// ecore_x_sync();
-// ecore_x_randr_screen_current_size_get(root, &dww, &dhh, &dww2, &dhh2);
-// printf("RRR: cur size: %ix%i\n", dww,d hh);
+ for (i = 0; i < crtcs_num; i++)
+ {
+ if ((screenconf) && (screenconf[i]))
+ {
+ ecore_x_randr_crtc_panning_area_set
+ (root, crtcs[i],
+ screenconf[i]->config.geom.x,
+ screenconf[i]->config.geom.y,
+ screenconf[i]->config.geom.w,
+ screenconf[i]->config.geom.h);
+ }
+ }
}
+ free(crtcs);
+
ecore_x_randr_screen_size_range_get(root, NULL, NULL, NULL, NULL);
- ecore_x_ungrab();
ecore_x_sync();
// ignore the next batch of randr events - we caused them ourselves
// XXX: a problem. thew first time we configure the screen we may not
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.