Skip to content

Commit 3fb41cc

Browse files
committed
Fix flashing during window resizing.
The root cause of flashing/flickering was that on each resize event, AppKit called drawRect: on the MMCoreTextView, expecting it to fill an empty, newly-sized buffer with content. It has nothing to draw, so the view would show up as black until the BatchDrawMsgID reply arrived from the backend and triggered another draw. (The MMCoreTextView was display:ed twice for each resize). This change does three things: 1. Implements -[MMCoreTextView setFrameSize:] to begin an NSAnimationContext grouping before calling super, which postpones display:/drawRect: until the grouping ends, and ends the grouping in performBatchDrawWithData:. 2. Makes *all* resize messages sent to the backend synchronous, with a 1s timeout. This seems bad, but actually helps avoid spamming the backend with resize events, since the app only generates resize events as fast as we handle them (i.e. if we take time to process one resize, then the next resize event will have the current size of the window, potentially skipping a bunch in the middle that the backend never would have had time to handle). 3. Gets rid of some hacks resolved by 1 and 2, like MKVimController delaying the call to -[MMWindowController presentWindow:].
1 parent 98496b9 commit 3fb41cc

File tree

5 files changed

+18
-46
lines changed

5 files changed

+18
-46
lines changed

src/MacVim/MMCoreTextView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
BOOL antialias;
3232
BOOL ligatures;
3333
BOOL thinStrokes;
34+
BOOL drawPending;
3435
NSMutableArray *drawData;
3536

3637
MMTextViewHelper *helper;
@@ -96,6 +97,7 @@
9697
//
9798
// NSTextView methods
9899
//
100+
- (void)setFrameSize:(NSSize)newSize;
99101
- (void)keyDown:(NSEvent *)event;
100102
- (void)insertText:(id)string;
101103
- (void)doCommandBySelector:(SEL)selector;

src/MacVim/MMCoreTextView.m

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,14 @@ - (BOOL)_wantsKeyDownForEvent:(id)event
446446
return YES;
447447
}
448448

449+
- (void)setFrameSize:(NSSize)newSize {
450+
if (!drawPending && !NSEqualSizes(newSize, self.frame.size) && drawData.count == 0) {
451+
[NSAnimationContext beginGrouping];
452+
drawPending = YES;
453+
}
454+
[super setFrameSize:newSize];
455+
}
456+
449457
- (void)keyDown:(NSEvent *)event
450458
{
451459
[helper keyDown:event];
@@ -650,11 +658,10 @@ - (void)performBatchDrawWithData:(NSData *)data
650658
} else {
651659
[drawData addObject:data];
652660
[self setNeedsDisplay:YES];
653-
654-
// NOTE: During resizing, Cocoa only sends draw messages before Vim's rows
655-
// and columns are changed (due to ipc delays). Force a redraw here.
656-
if ([self inLiveResize])
657-
[self display];
661+
}
662+
if (drawPending) {
663+
[NSAnimationContext endGrouping];
664+
drawPending = NO;
658665
}
659666
}
660667

src/MacVim/MMVimController.m

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -554,15 +554,9 @@ - (void)handleMessage:(int)msgid data:(NSData *)data
554554
{
555555
if (OpenWindowMsgID == msgid) {
556556
[windowController openWindow];
557-
558-
// HACK: Delay actually presenting the window onscreen until after
559-
// processing the queue since it contains drawing commands that need to
560-
// be issued before presentation; otherwise the window may flash white
561-
// just as it opens.
562-
if (!isPreloading)
563-
[windowController performSelector:@selector(presentWindow:)
564-
withObject:nil
565-
afterDelay:0];
557+
if (!isPreloading) {
558+
[windowController presentWindow:nil];
559+
}
566560
} else if (BatchDrawMsgID == msgid) {
567561
[[[windowController vimView] textView] performBatchDrawWithData:data];
568562
} else if (SelectTabMsgID == msgid) {

src/MacVim/MMVimView.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ - (void)frameSizeMayHaveChanged
909909
"%dx%d (%s)", cols, rows, constrained[1], constrained[0],
910910
MessageStrings[msgid]);
911911

912-
[vimController sendMessage:msgid data:data];
912+
[vimController sendMessageNow:msgid data:data timeout:1];
913913

914914
// We only want to set the window title if this resize came from
915915
// a live-resize, not (for example) setting 'columns' or 'lines'.

src/MacVim/MMWindowController.m

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -697,37 +697,6 @@ - (void)liveResizeDidEnd
697697
NSConnection *connection = [(NSDistantObject*)proxy connectionForProxy];
698698
[connection removeRequestMode:NSEventTrackingRunLoopMode];
699699

700-
// NOTE: During live resize messages from MacVim to Vim are often dropped
701-
// (because too many messages are sent at once). This may lead to
702-
// inconsistent states between Vim and MacVim; to avoid this we send a
703-
// synchronous resize message to Vim now (this is not fool-proof, but it
704-
// does seem to work quite well).
705-
// Do NOT send a SetTextDimensionsMsgID message (as opposed to
706-
// LiveResizeMsgID) since then the view is constrained to not be larger
707-
// than the screen the window mostly occupies; this makes it impossible to
708-
// resize the window across multiple screens.
709-
710-
int constrained[2];
711-
NSSize textViewSize = [[vimView textView] frame].size;
712-
[[vimView textView] constrainRows:&constrained[0] columns:&constrained[1]
713-
toSize:textViewSize];
714-
715-
ASLogDebug(@"End of live resize, notify Vim that text dimensions are %dx%d",
716-
constrained[1], constrained[0]);
717-
718-
NSData *data = [NSData dataWithBytes:constrained length:2*sizeof(int)];
719-
BOOL sendOk = [vimController sendMessageNow:LiveResizeMsgID
720-
data:data
721-
timeout:.5];
722-
723-
if (!sendOk) {
724-
// Sending of synchronous message failed. Force the window size to
725-
// match the last dimensions received from Vim, otherwise we end up
726-
// with inconsistent states.
727-
[self resizeWindowToFitContentSize:[vimView desiredSize]
728-
keepOnScreen:NO];
729-
}
730-
731700
// If we saved the original title while resizing, restore it.
732701
if (lastSetTitle != nil) {
733702
[decoratedWindow setTitle:lastSetTitle];

0 commit comments

Comments
 (0)