Allows smooth resizing of MacVim's window

Adds a setting that allows for smoothly resizing the window. Previously,
MacVim would only allow resizing in fixed increment of the grid size and
snap to such sizes. This was a little more consistent with how terminals
tend to work, and allows for optimal window sizing, and it was also an
artifact of the old MacVim renderer where it didn't have a stateful
renderer that could repaint the text view.

The snapping could be jarring for users more used to modern text editors
which allow for smoothly resizing of the window though, and it makes
third party tools that could snap macOS windows to the side not work
properly as there's usually a gap near the bottom. With guioption-k,
MacVim already allows for decoupling the window size from the Vim's grid
size anyway, so adding smooth resizing allows to work much better under
those assumptions.

In addition to allowing smooth resizing, this change also makes it so
that the CoreText renderer will fill to the right a little bit when
rendering the rightmost column when MacVim's window size isn't exactly
the Vim grid size. Previously, if a color scheme has NonText color (e.g.
desert), or the user has 'cursorline' set, smooth resize (or in full
screen or guioption-k) would leave a gap to the right, looking a little
ugly. This allows the last column's to fully fill to the right,
resulting in a much more consistent look when resizing the window.

Close #948
This commit is contained in:
Yee Cheng Chin
2022-09-10 21:52:04 -07:00
parent 801217e02c
commit aa1c720306
12 changed files with 135 additions and 28 deletions
+1
View File
@@ -273,6 +273,7 @@ KEY VALUE ~
*MMNoTitleBarWindow* hide title bar [bool]
*MMTitlebarAppearsTransparent* enable a transparent titlebar [bool]
*MMAppearanceModeSelection* dark mode selection (|macvim-dark-mode|)[bool]
*MMSmoothResize* allow smooth resizing of MacVim window [bool]
*MMShareFindPboard* share search text to Find Pasteboard [bool]
*MMShowAddTabButton* enable "add tab" button on tabline [bool]
*MMTabMaxWidth* maximum width of a tab [int]
+1
View File
@@ -5418,6 +5418,7 @@ MMNonNativeFullScreenSafeAreaBehavior gui_mac.txt /*MMNonNativeFullScreenSafeAre
MMNonNativeFullScreenShowMenu gui_mac.txt /*MMNonNativeFullScreenShowMenu*
MMShareFindPboard gui_mac.txt /*MMShareFindPboard*
MMShowAddTabButton gui_mac.txt /*MMShowAddTabButton*
MMSmoothResize gui_mac.txt /*MMSmoothResize*
MMTabMaxWidth gui_mac.txt /*MMTabMaxWidth*
MMTabMinWidth gui_mac.txt /*MMTabMinWidth*
MMTabOptimumWidth gui_mac.txt /*MMTabOptimumWidth*
+38 -10
View File
@@ -20,12 +20,12 @@
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<userDefaultsController representsSharedInstance="YES" id="58" userLabel="Shared Defaults"/>
<customView id="115" userLabel="General">
<rect key="frame" x="0.0" y="0.0" width="483" height="314"/>
<rect key="frame" x="0.0" y="0.0" width="483" height="337"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView id="5x5-P0-afk" userLabel="Open untitled window">
<rect key="frame" x="19" y="234" width="433" height="58"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<rect key="frame" x="20" y="259" width="433" height="58"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="117">
<rect key="frame" x="-2" y="41" width="187" height="17"/>
@@ -70,8 +70,8 @@
</subviews>
</customView>
<customView id="p6o-fo-STi" userLabel="Open files from applications">
<rect key="frame" x="19" y="94" width="433" height="132"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<rect key="frame" x="20" y="119" width="433" height="132"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="116">
<rect key="frame" x="-2" y="115" width="187" height="17"/>
@@ -149,8 +149,8 @@
</subviews>
</customView>
<customView id="dlz-JQ-U4e" userLabel="After last window closes">
<rect key="frame" x="19" y="66" width="381" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<rect key="frame" x="20" y="89" width="381" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="126">
<rect key="frame" x="-2" y="3" width="187" height="17"/>
@@ -182,9 +182,37 @@
</popUpButton>
</subviews>
</customView>
<customView id="6BL-o0-OrR" userLabel="Window Resizing">
<rect key="frame" x="20" y="64" width="444" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button id="f9h-8n-asD" userLabel="allow smooth resizing">
<rect key="frame" x="188" y="-1" width="258" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<string key="toolTip">Smoothly resizes MacVim's window instead of fixing it to the grid size. It's also recommended to set "guioptions+=k" in your vimrc when this is set.</string>
<buttonCell key="cell" type="check" title="Smoothly resizes window" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="4YN-AX-Vrz">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="smoothResizeChanged:" target="-2" id="paG-Lx-hcb"/>
<binding destination="58" name="value" keyPath="values.MMSmoothResize" id="Wkt-gU-ZnK"/>
</connections>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="Lmi-H0-cPd" userLabel="Window resizing">
<rect key="frame" x="-2" y="0.0" width="187" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Resizing window:" id="ExQ-6y-pyN" userLabel="Window resizing:">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</customView>
<customView id="0hT-y8-Hge" userLabel="Updater">
<rect key="frame" x="19" y="22" width="444" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<rect key="frame" x="20" y="20" width="444" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<button id="122">
<rect key="frame" x="188" y="18" width="258" height="18"/>
@@ -226,7 +254,7 @@
</subviews>
</customView>
</subviews>
<point key="canvasLocation" x="138" y="20"/>
<point key="canvasLocation" x="137.5" y="21.5"/>
</customView>
<customView id="hr4-G4-3ZG" userLabel="Appearance">
<rect key="frame" x="0.0" y="0.0" width="483" height="315"/>
+1
View File
@@ -60,6 +60,7 @@
- (void)refreshAllAppearances;
- (void)refreshAllFonts;
- (void)refreshAllResizeConstraints;
- (IBAction)newWindow:(id)sender;
- (IBAction)newWindowAndActivate:(id)sender;
+10
View File
@@ -252,6 +252,7 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
[NSNumber numberWithBool:NO], MMNonNativeFullScreenShowMenuKey,
[NSNumber numberWithInt:0], MMNonNativeFullScreenSafeAreaBehaviorKey,
[NSNumber numberWithBool:YES], MMShareFindPboardKey,
[NSNumber numberWithBool:NO], MMSmoothResizeKey,
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dict];
@@ -1132,6 +1133,15 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
}
}
- (void)refreshAllResizeConstraints
{
const unsigned count = [vimControllers count];
for (unsigned i = 0; i < count; ++i) {
MMVimController *vc = [vimControllers objectAtIndex:i];
[vc.windowController updateResizeConstraints:YES];
}
}
- (IBAction)newWindow:(id)sender
{
ASLogDebug(@"Open new window");
+37 -1
View File
@@ -835,10 +835,26 @@ static void grid_free(Grid *grid) {
cell.fg ^= 0xFFFFFF;
cell.sp ^= 0xFFFFFF;
}
// Fill background
if (cell.bg != defaultBg && ALPHA(cell.bg) > 0) {
CGRect fillCellRect = cellRect;
if (c == grid.cols - 1 || (c == grid.cols - 2 && (cell.textFlags & DRAW_WIDE))) {
// Fill a little extra to the right if this is the last
// column, and the frame size isn't exactly the same size
// as the grid (due to smooth resizing, etc). This makes it
// look less ugly and more consisten. See rectForRow:'s
// implementation for extra comments.
CGFloat extraWidth = rowRect.origin.x + rowRect.size.width - (cellRect.size.width + cellRect.origin.x);
fillCellRect.size.width += extraWidth;
}
CGContextSetFillColor(ctx, COMPONENTS(cell.bg));
CGContextFillRect(ctx, cellRect);
CGContextFillRect(ctx, fillCellRect);
}
// Handle signs
if (cell.sign) {
CGRect signRect = cellRect;
signRect.size.width *= 2;
@@ -847,6 +863,8 @@ static void grid_free(Grid *grid) {
operation:(cell.inverted ? NSCompositingOperationDifference : NSCompositingOperationSourceOver)
fraction:1.0];
}
// Insertion point (cursor)
if (cell.insertionPoint.color && cell.insertionPoint.fraction) {
float frac = cell.insertionPoint.fraction / 100.0;
NSRect rect = cellRect;
@@ -867,6 +885,8 @@ static void grid_free(Grid *grid) {
NSRectFill(rect);
}
}
// Text underline styles
if (cell.textFlags & DRAW_UNDERL) {
CGRect rect = CGRectMake(cellRect.origin.x, cellRect.origin.y+0.4*fontDescent, cellRect.size.width, 1);
CGContextSetFillColor(ctx, COMPONENTS(cell.sp));
@@ -879,6 +899,8 @@ static void grid_free(Grid *grid) {
CGContextSetRGBStrokeColor(ctx, RED(cell.sp), GREEN(cell.sp), BLUE(cell.sp), ALPHA(cell.sp));
CGContextStrokePath(ctx);
}
// Draw the actual text
if (cell.string) {
if (!ligatures || lastStringCell.fg != cell.fg || lastStringCell.textFlags != cell.textFlags)
flushLineString();
@@ -894,6 +916,7 @@ static void grid_free(Grid *grid) {
} else {
flushLineString();
}
if (cell.textFlags & DRAW_WIDE)
c++;
}
@@ -1067,6 +1090,19 @@ static void grid_free(Grid *grid) {
rect.size.width = nc*cellSize.width;
rect.size.height = nr*cellSize.height;
// Under smooth resizing, full screen, or guioption-k; we frequently have a frame size that's not
// aligned with the exact grid size. If the user has 'cursorline' set, or the color scheme uses
// the NonText highlight group, this will leave a small gap on the right filled with bg color looking
// a little weird. Just fill a little extra to the right for the last column to make it look less weird.
//
// Note that we don't do this for filling the bottom since it's used only for cmdline which isn't usually
// colored anyway.
if (col + nc == grid.cols) {
const int insetRight = [[NSUserDefaults standardUserDefaults] integerForKey:MMTextInsetRightKey];
CGFloat extraWidth = frame.size.width - insetRight - (rect.size.width + rect.origin.x);
rect.size.width += extraWidth;
}
return rect;
}
+7
View File
@@ -27,4 +27,11 @@
- (IBAction)openInCurrentWindowSelectionChanged:(id)sender;
- (IBAction)checkForUpdatesChanged:(id)sender;
- (IBAction)appearanceChanged:(id)sender;
- (IBAction)lastWindowClosedChanged:(id)sender;
- (IBAction)openUntitledWindowChanged:(id)sender;
- (IBAction)smoothResizeChanged:(id)sender;
// Appearance pane
- (IBAction)fontPropertiesChanged:(id)sender;
@end
+5
View File
@@ -163,4 +163,9 @@
}
}
- (IBAction)smoothResizeChanged:(id)sender
{
[[MMAppController sharedInstance] refreshAllResizeConstraints];
}
@end
+1
View File
@@ -77,6 +77,7 @@
- (void)setBackgroundOption:(int)dark;
- (void)refreshApperanceMode;
- (void)updateResizeConstraints:(BOOL)resizeWindow;
- (void)setDefaultColorsBackground:(NSColor *)back foreground:(NSColor *)fore;
- (void)setFont:(NSFont *)font;
+32 -17
View File
@@ -86,7 +86,6 @@
keepOnScreen:(BOOL)onScreen;
- (NSSize)constrainContentSizeToScreenSize:(NSSize)contentSize;
- (NSRect)constrainFrame:(NSRect)frame;
- (void)updateResizeConstraints;
- (NSTabViewItem *)addNewTabViewItem;
- (BOOL)askBackendForStarRegister:(NSPasteboard *)pb;
- (void)updateTablineSeparator;
@@ -332,7 +331,7 @@
// code that is executed before this point must not depend on the screen!
[[MMAppController sharedInstance] windowControllerWillOpen:self];
[self updateResizeConstraints];
[self updateResizeConstraints:NO];
[self resizeWindowToFitContentSize:[vimView desiredSize]
keepOnScreen:YES];
@@ -707,7 +706,7 @@
}
[[vimView textView] setFont:font];
[self updateResizeConstraints];
[self updateResizeConstraints:NO];
shouldMaximizeWindow = YES;
}
@@ -1519,6 +1518,35 @@
}
#endif
/// This will update the window's resizing constraints to either be smooth or rounded to whole cells.
///
/// @param resizeWindow If specified, will also resize the window itself down to match the Vim view's desired size.
- (void)updateResizeConstraints:(BOOL)resizeWindow
{
if (!setupDone) return;
// If smooth resizing is not set, set the resize increments to exactly
// match the font size; this way the window will always hold an integer
// number of (rows,columns). Otherwise, just allow arbitrary resizing.
const BOOL smoothResize = [[NSUserDefaults standardUserDefaults] boolForKey:MMSmoothResizeKey];
const NSSize desiredResizeConstraints = smoothResize ?
NSMakeSize(1, 1) :
[[vimView textView] cellSize];
[decoratedWindow setContentResizeIncrements:desiredResizeConstraints];
const NSSize minSize = [vimView minSize];
[decoratedWindow setContentMinSize:minSize];
if (resizeWindow) {
if (!smoothResize) {
// We only want to resize the window down to match the Vim size if not using smooth resizing.
// This resizing is going to re-snap the Window size to multiples of grid size. Otherwise
// the resize constraint is always going to be at an offset to the desired size.
shouldResizeVimView = YES;
}
}
}
@end // MMWindowController
@@ -1645,19 +1673,6 @@
return [decoratedWindow frameRectForContentRect:contentRect];
}
- (void)updateResizeConstraints
{
if (!setupDone) return;
// Set the resize increments to exactly match the font size; this way the
// window will always hold an integer number of (rows,columns).
NSSize cellSize = [[vimView textView] cellSize];
[decoratedWindow setContentResizeIncrements:cellSize];
NSSize minSize = [vimView minSize];
[decoratedWindow setContentMinSize:minSize];
}
- (NSTabViewItem *)addNewTabViewItem
{
return [vimView addNewTabViewItem];
@@ -1711,7 +1726,7 @@
if ([decoratedWindow hideTablineSeparator:hide]) {
// The tabline separator was toggled so the content view must change
// size.
[self updateResizeConstraints];
[self updateResizeConstraints:NO];
}
}
+1
View File
@@ -58,6 +58,7 @@ extern NSString *MMUseMouseTimeKey;
extern NSString *MMFullScreenFadeTimeKey;
extern NSString *MMNonNativeFullScreenShowMenuKey;
extern NSString *MMNonNativeFullScreenSafeAreaBehaviorKey;
extern NSString *MMSmoothResizeKey;
// Enum for MMUntitledWindowKey
+1
View File
@@ -54,6 +54,7 @@ NSString *MMUseMouseTimeKey = @"MMUseMouseTime";
NSString *MMFullScreenFadeTimeKey = @"MMFullScreenFadeTime";
NSString *MMNonNativeFullScreenShowMenuKey = @"MMNonNativeFullScreenShowMenu";
NSString *MMNonNativeFullScreenSafeAreaBehaviorKey = @"MMNonNativeFullScreenSafeAreaBehavior";
NSString *MMSmoothResizeKey = @"MMSmoothResize";