mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-07 15:37:14 +02:00
Fixed native fullscreen rendering corruption bug
Fix the issue where MacVim would occasionally draws corrupted image in fullscreen (it would draw mostly black). The easiest way to reproduce this is as follows: 1. Make a new MacVim window, enter fullscreen 2. Open a new tab or hit Cmd-= a few times 3. Switch to another fullscreen app or desktop, click around, then switch back 4. Observe most of the screen is black. The reason this happens is that the MacVim resize code always tries to resize the window to fit the content size (calculated from how many lines / columns we have and whether other elements like tab bar are visible). This means the resize code (resizeWindowToFitContentSize:keepOnScreen:) would make the window smaller than the full size of screen. For some reason, when you switch away from the space, macOS decides to resize the window back to screen size again, causing a window resize event to happen. The resize event invalidates the NSView, causing it to draw black. This is also why fullscreen mode has black bars on top / bottom, which is especially jarring when font size is large of `linespace` is high. The fix is to treat guioptions 'k' to be on when in full screen mode, since the option means we will always try to fit the Vim content inside the window, rather than resize the window to fit the Vim content. This way the fullscreen Vim window will take up the whole screen and won't keep getting resized. This is also more similar to how native Gvim works when maximized. Close #496 (black bars) Close #557, close #674 (full screen rendering issues) A related issue is that MacVim (without CGLayer backing) doesn't actually know how to redraw itself properly when invalidated, which is the root cause of this bug. It receives Vim draw calls incrementally and doesn't actually cache the rendered content, so it relies on the fact that MacVim's NSWindow doesn't usually invalidates all the content which allows it to draw incrementally without needing to perform a full redraw. This is why non-native fullscreen requires CGLayer backing mode as macOS's behavior in this mode (basically a borderless window) is that it does clear the NSWindow's content when setWantsDisplay: is called. This is also why Vim live window resizing is limited to cell size instead of allowing smooth resize (to avoid having to trigger redraws). These are issues that should be fixed later.
This commit is contained in:
@@ -599,39 +599,27 @@
|
||||
if (!didMaximize) {
|
||||
NSSize originalSize = [vimView frame].size;
|
||||
int rows = 0, cols = 0;
|
||||
NSSize contentSize = [vimView constrainRows:&rows columns:&cols
|
||||
toSize:
|
||||
fullScreenWindow ? [fullScreenWindow frame].size :
|
||||
fullScreenEnabled ? desiredWindowSize :
|
||||
[self constrainContentSizeToScreenSize:[vimView desiredSize]]];
|
||||
|
||||
// Setting 'guioptions+=k' will make shouldKeepGUISize true, which
|
||||
// means avoid resizing the window. Instead, resize the view instead
|
||||
// to keep the GUI window's size consistent.
|
||||
bool avoidWindowResize = shouldKeepGUISize && !fullScreenEnabled;
|
||||
bool avoidWindowResize = shouldKeepGUISize || fullScreenEnabled;
|
||||
|
||||
if (!avoidWindowResize) {
|
||||
NSSize contentSize = [vimView constrainRows:&rows columns:&cols
|
||||
toSize:
|
||||
fullScreenWindow ? [fullScreenWindow frame].size :
|
||||
fullScreenEnabled ? desiredWindowSize :
|
||||
[self constrainContentSizeToScreenSize:[vimView desiredSize]]];
|
||||
|
||||
[vimView setFrameSize:contentSize];
|
||||
|
||||
[self resizeWindowToFitContentSize:contentSize
|
||||
keepOnScreen:keepOnScreen];
|
||||
}
|
||||
else {
|
||||
[vimView setFrameSizeKeepGUISize:originalSize];
|
||||
}
|
||||
|
||||
if (fullScreenWindow) {
|
||||
// NOTE! Don't mark the full-screen content view as needing an
|
||||
// update unless absolutely necessary since when it is updated
|
||||
// the entire screen is cleared. This may cause some parts of
|
||||
// the Vim view to be cleared but not redrawn since Vim does
|
||||
// not realize that we've erased part of the view.
|
||||
if (!NSEqualSizes(originalSize, contentSize)) {
|
||||
[[fullScreenWindow contentView] setNeedsDisplay:YES];
|
||||
[fullScreenWindow centerView];
|
||||
}
|
||||
} else {
|
||||
if (!avoidWindowResize) {
|
||||
[self resizeWindowToFitContentSize:contentSize
|
||||
keepOnScreen:keepOnScreen];
|
||||
}
|
||||
NSSize frameSize = fullScreenWindow ? [fullScreenWindow frame].size : (fullScreenEnabled ? desiredWindowSize : originalSize);
|
||||
[vimView setFrameSizeKeepGUISize:frameSize];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user