Skip to content

Commit dc9679c

Browse files
committed
SystemKit: fix framebuffer sizing so single-axis resolution changes apply
applyDisplayLayout: enlarged the X framebuffer only when BOTH dimensions grew (&&) and shrank it only when one dimension got smaller (||). A change that altered a single axis - e.g. 1400x1050 -> 1680x1050, same height - matched neither branch, so the framebuffer stayed at the old size while a wider CRTC mode was requested. XRRSetCrtcConfig then failed with BadMatch, the mode never took effect, and the display showed a black band on the right (xrandr still reported the old 1400x1050 screen). Grow the framebuffer up front to the per-axis maximum of the current and new sizes so the new mode always fits, then set it to the exact final size after all CRTCs are placed. This preserves the original VirtualBox BadMatch safeguard (the framebuffer is never shrunk below the still-current layout mid-transition) while covering single-axis and mixed grow/shrink changes.
1 parent e5d55ef commit dc9679c

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

Frameworks/SystemKit/OSEScreen.m

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,17 +1091,22 @@ - (BOOL)applyDisplayLayout:(NSArray *)layout
10911091

10921092
[updateScreenLock lock];
10931093

1094-
/* If new screen size is BIGGER - set new screen size here
1095-
Example: current size is 1440x900, new size 1280x960. Height is bigger
1096-
but width is smaller. In VirtualBox this leads to - X Error:
1097-
BadMatch (invalid parameter attributes). */
1098-
if (newPixSize.width > sizeInPixels.width &&
1094+
/* If either dimension GROWS, enlarge the framebuffer up front to the
1095+
per-axis maximum of the current and new sizes, so the new CRTC mode
1096+
always fits. Growing only when BOTH dimensions increase left the
1097+
framebuffer too narrow/short when just one dimension changed (e.g.
1098+
1400x1050 -> 1680x1050): XRRSetCrtcConfig then failed with BadMatch and
1099+
the display showed a black band. Using the union (not newPixSize) keeps
1100+
the framebuffer large enough for the still-current layout during the
1101+
transition. */
1102+
if (newPixSize.width > sizeInPixels.width ||
10991103
newPixSize.height > sizeInPixels.height) {
1100-
NSDebugLLog(@"Screen", @"OSEScreen: set new BIGGER screen size: START");
1104+
NSDebugLLog(@"Screen", @"OSEScreen: grow screen size to union: START");
11011105
XRRSetScreenSize(xDisplay, xRootWindow,
1102-
(int)newPixSize.width, (int)newPixSize.height,
1106+
(int)MAX(newPixSize.width, sizeInPixels.width),
1107+
(int)MAX(newPixSize.height, sizeInPixels.height),
11031108
(int)mmSize.width, (int)mmSize.height);
1104-
NSDebugLLog(@"Screen", @"OSEScreen: set new BIGGER screen size: END");
1109+
NSDebugLLog(@"Screen", @"OSEScreen: grow screen size to union: END");
11051110
}
11061111

11071112
// Set resolution and gamma to displays
@@ -1143,14 +1148,16 @@ - (BOOL)applyDisplayLayout:(NSArray *)layout
11431148
[display setGammaFromDescription:gamma];
11441149
}
11451150

1146-
// If new screen size is SMALLER - set new screen size here
1147-
if (newPixSize.width < sizeInPixels.width ||
1148-
newPixSize.height < sizeInPixels.height) {
1149-
NSDebugLLog(@"Screen", @"OSEScreen: set new SMALLER screen size: START");
1151+
// All CRTCs are now placed within the (possibly grown) framebuffer, so set
1152+
// it to the exact final size. This shrinks it back when growing only one
1153+
// dimension or when the new layout is smaller.
1154+
if (newPixSize.width != sizeInPixels.width ||
1155+
newPixSize.height != sizeInPixels.height) {
1156+
NSDebugLLog(@"Screen", @"OSEScreen: set final screen size: START");
11501157
XRRSetScreenSize(xDisplay, xRootWindow,
11511158
(int)newPixSize.width, (int)newPixSize.height,
11521159
(int)mmSize.width, (int)mmSize.height);
1153-
NSDebugLLog(@"Screen", @"OSEScreen: set new SMALLER screen size: END");
1160+
NSDebugLLog(@"Screen", @"OSEScreen: set final screen size: END");
11541161
}
11551162

11561163
sizeInPixels = newPixSize;

0 commit comments

Comments
 (0)