Skip to content

Fix native fullscreen rendering and resizing bugs #745

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/MacVim/MMVimView.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
NSMutableArray *scrollbars;
}

@property BOOL pendingLiveResize;

- (MMVimView *)initWithFrame:(NSRect)frame vimController:(MMVimController *)c;

- (MMTextView *)textView;
Expand Down
14 changes: 13 additions & 1 deletion src/MacVim/MMVimView.m
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,19 @@ - (void)frameSizeMayHaveChanged:(BOOL)keepGUISize
"%dx%d (%s)", cols, rows, constrained[1], constrained[0],
MessageStrings[msgid]);

[vimController sendMessageNow:msgid data:data timeout:1];
if (msgid != LiveResizeMsgID || !self.pendingLiveResize) {
// Live resize messages can be sent really rapidly, especailly if
// it's from double clicking the window border (to indicate filling
// all the way to that side to the window manager). We want to rate
// limit sending live resize one at a time, or the IPC will get
// swamped which causes slowdowns and some messages will also be dropped.
// As a result we basically discard all live resize messages if one
// is already going on. liveResizeDidEnd: will perform a final clean
// up resizing.
self.pendingLiveResize = (msgid == LiveResizeMsgID);

[vimController sendMessageNow:msgid data:data timeout:1];
}

// We only want to set the window title if this resize came from
// a live-resize, not (for example) setting 'columns' or 'lines'.
Expand Down
56 changes: 24 additions & 32 deletions src/MacVim/MMWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ - (void)setTextDimensionsWithRows:(int)rows columns:(int)cols isLive:(BOOL)live
// user drags to resize the window.

[vimView setDesiredRows:rows columns:cols];
vimView.pendingLiveResize = NO;

if (setupDone && !live && !keepGUISize) {
shouldResizeVimView = YES;
Expand Down Expand Up @@ -599,39 +600,27 @@ - (void)processInputQueueDidFinish
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];
}
}

Expand Down Expand Up @@ -724,6 +713,13 @@ - (void)liveResizeDidEnd
[lastSetTitle release];
lastSetTitle = nil;
}

// If we are in the middle of rapid resize (e.g. double-clicking on the border/corner
// of window), we would fire off a lot of LiveResizeMsgID messages where some will be
// intentionally omitted to avoid swamping IPC. If that happens this will perform a
// final clean up that makes sure the Vim view is sized correctly within the window.
// See frameSizeMayHaveChanged: for where the omission/rate limiting happens.
[self resizeView];
}

- (void)setBlurRadius:(int)radius
Expand Down Expand Up @@ -1059,14 +1055,10 @@ - (void)windowDidResize:(id)sender
// may resize automatically) we simply set the view to fill the entire
// window. The vim view takes care of notifying Vim if the number of
// (rows,columns) changed.
if (shouldKeepGUISize) {
// This happens when code manually call setFrame: when we are performing
// an operation that wants to preserve GUI size (e.g. in updateToolbar:).
// Respect the wish, and pass that along.
[vimView setFrameSizeKeepGUISize:[self contentSize]];
} else {
[vimView setFrameSize:[self contentSize]];
}
// Calling setFrameSizeKeepGUISize: instead of setFrameSize: prevents a
// degenerate case where frameSizeMayHaveChanged: ends up resizing the window
// *again* causing windowDidResize: to be called.
[vimView setFrameSizeKeepGUISize:[self contentSize]];
}

- (void)windowDidChangeBackingProperties:(NSNotification *)notification
Expand Down