Skip to content

Add better scroll wheel support and option to disable acceleration #1566

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 1 commit into from
Feb 23, 2025
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
15 changes: 11 additions & 4 deletions runtime/doc/gui_mac.txt
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,6 @@ as general information regarding macOS user defaults.
Here is a list of relevant dictionary entries:

KEY VALUE ~
*MMAllowForceClickLookUp* use Force click for data lookup instead of
<ForceClick> [bool]
*MMCellWidthMultiplier* width of a normal glyph in em units [float]
*MMCmdLineAlignBottom* Pin command-line to bottom of MacVim [bool]
*MMDialogsTrackPwd* open/save dialogs track the Vim pwd [bool]
Expand All @@ -307,7 +305,6 @@ KEY VALUE ~
*MMTitlebarAppearsTransparent* enable a transparent titlebar [bool]
*MMAppearanceModeSelection* dark mode selection (|macvim-dark-mode|)[bool]
*MMRendererClipToRow* clip tall characters to the row they are on [bool]
*MMScrollOneDirectionOnly* scroll along one axis only when using trackpad [bool]
*MMSmoothResize* allow smooth resizing of MacVim window [bool]
*MMShareFindPboard* share search text to Find Pasteboard [bool]
*MMTextInsetBottom* text area offset in pixels [int]
Expand All @@ -316,12 +313,22 @@ KEY VALUE ~
*MMTextInsetTop* text area offset in pixels [int]
*MMTexturedWindow* use brushed metal window (Tiger only) [bool]
*MMTranslateCtrlClick* interpret ctrl-click as right-click [bool]
*MMUseMouseTime* use mousetime to detect multiple clicks [bool]
*MMVerticalSplit* files open in vertical splits [bool]
*MMZoomBoth* zoom button maximizes both directions [bool]
*MMUpdaterPrereleaseChannel* opt-in to pre-release software update [bool]
*MMShowWhatsNewOnStartup* show "What's New" after updating to new version [bool]

Mouse / Trackpad ~
*MMScrollOneDirectionOnly* scroll along one axis only when using trackpad [bool]
*MMAllowForceClickLookUp* use Force click for data lookup instead of
<ForceClick> [bool]
*MMMouseWheelDisableAcceleration* disable OS scroll wheel acceleration [bool]
*MMMouseWheelNumLines* how many lines to scroll when scroll wheel
acceleration is turned off [int]
*MMMouseWheelMinLines* min number of lines to scroll per scroll wheel
click when acceleration is on [int]
*MMUseMouseTime* use mousetime to detect multiple clicks [bool]

Tabs ~
*MMTabColorsMode* use default/auto/colorscheme for tab colors [int]
*MMWindowUseTabBackgroundColor* use tabs background fill color as window color [bool]
Expand Down
3 changes: 3 additions & 0 deletions runtime/doc/tags
Original file line number Diff line number Diff line change
Expand Up @@ -5654,6 +5654,9 @@ MMFullScreenFadeTime gui_mac.txt /*MMFullScreenFadeTime*
MMLoginShell gui_mac.txt /*MMLoginShell*
MMLoginShellArgument gui_mac.txt /*MMLoginShellArgument*
MMLoginShellCommand gui_mac.txt /*MMLoginShellCommand*
MMMouseWheelDisableAcceleration gui_mac.txt /*MMMouseWheelDisableAcceleration*
MMMouseWheelMinLines gui_mac.txt /*MMMouseWheelMinLines*
MMMouseWheelNumLines gui_mac.txt /*MMMouseWheelNumLines*
MMNativeFullScreen gui_mac.txt /*MMNativeFullScreen*
MMNoFontSubstitution gui_mac.txt /*MMNoFontSubstitution*
MMNoTitleBarWindow gui_mac.txt /*MMNoTitleBarWindow*
Expand Down
47 changes: 42 additions & 5 deletions src/MacVim/Base.lproj/Preferences.xib
Original file line number Diff line number Diff line change
Expand Up @@ -573,11 +573,11 @@
<point key="canvasLocation" x="137.5" y="478.5"/>
</customView>
<customView id="Bnq-Nx-GJH" userLabel="Input">
<rect key="frame" x="0.0" y="0.0" width="483" height="110"/>
<rect key="frame" x="0.0" y="0.0" width="483" height="155"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<customView id="DAP-Yi-QU0" userLabel="Trackpad">
<rect key="frame" x="20" y="72" width="433" height="18"/>
<rect key="frame" x="20" y="117" width="433" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="f18-Wr-EgZ">
Expand All @@ -604,11 +604,11 @@
</subviews>
</customView>
<customView id="GZa-RH-fza" userLabel="Mouse">
<rect key="frame" x="20" y="46" width="433" height="18"/>
<rect key="frame" x="20" y="46" width="433" height="63"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="3Tx-8j-zQR">
<rect key="frame" x="-2" y="0.0" width="187" height="17"/>
<rect key="frame" x="-2" y="45" width="187" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Mouse:" id="imK-Tr-YuD">
<font key="font" metaFont="system"/>
Expand All @@ -617,7 +617,7 @@
</textFieldCell>
</textField>
<button id="RLs-2Z-8PJ" userLabel="Ctrl-click as right-click">
<rect key="frame" x="189" y="-1" width="199" height="18"/>
<rect key="frame" x="189" y="44" width="199" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Treat Ctrl-click as right-click" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="PYG-cd-wzL" userLabel="Ctrl-click as right-click">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
Expand All @@ -627,6 +627,43 @@
<binding destination="58" name="value" keyPath="values.MMTranslateCtrlClick" id="ZMh-R3-AYN"/>
</connections>
</button>
<button id="8rY-bA-ZQt">
<rect key="frame" x="189" y="26" width="224" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Disable scroll wheel acceleration" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="fRx-Gy-P0M">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="58" name="value" keyPath="values.MMMouseWheelDisbleAcceleration" id="899-jt-taC"/>
</connections>
</button>
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="SqW-DB-w7i">
<rect key="frame" x="210" y="3" width="109" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMinY="YES"/>
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Lines to scroll:" id="w03-Ox-2xg">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="58" name="enabled" keyPath="values.MMMouseWheelDisbleAcceleration" id="Mzw-pC-FbR"/>
</connections>
</textField>
<textField focusRingType="none" verticalHuggingPriority="750" id="Zpw-eU-7d1">
<rect key="frame" x="305" y="1" width="32" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="Vwr-3s-VFd">
<numberFormatter key="formatter" formatterBehavior="default10_4" numberStyle="decimal" formatWidth="-1" minimumIntegerDigits="1" maximumIntegerDigits="2000000000" maximumFractionDigits="3" id="NEj-vx-0Qo"/>
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="58" name="enabled" keyPath="values.MMMouseWheelDisbleAcceleration" id="i3X-ti-Cv8"/>
<binding destination="58" name="value" keyPath="values.MMMouseWheelNumLines" id="ecJ-lb-ghs"/>
</connections>
</textField>
</subviews>
</customView>
<customView id="aUx-jX-mJJ" userLabel="Scrolling">
Expand Down
3 changes: 3 additions & 0 deletions src/MacVim/MMAppController.m
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ + (void)registerDefaults
[NSNumber numberWithBool:YES], MMUseInlineImKey,
#endif // INCLUDE_OLD_IM_CODE
[NSNumber numberWithBool:NO], MMSuppressTerminationAlertKey,
[NSNumber numberWithBool:NO], MMMouseWheelDisableAccelerationKey,
[NSNumber numberWithInt:1], MMMouseWheelMinLinesKey,
[NSNumber numberWithInt:3], MMMouseWheelNumLinesKey,
[NSNumber numberWithBool:YES], MMNativeFullScreenKey,
[NSNumber numberWithDouble:0.0], MMFullScreenFadeTimeKey,
[NSNumber numberWithBool:NO], MMNonNativeFullScreenShowMenuKey,
Expand Down
44 changes: 36 additions & 8 deletions src/MacVim/MMTextViewHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,15 @@ - (void)doCommandBySelector:(SEL)sel
else interpretKeyEventsSwallowedKey = NO;
}

- (void)scrollWheel:(NSEvent *)event
- (void)calcScrollWheelDeltas:(NSEvent *)event x:(float *)x y:(float *)y eventFlags:(NSEventModifierFlags*)eventFlags
{
float dx = 0;
float dy = 0;

#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];

if ([event hasPreciseScrollingDeltas]) {
const NSEventPhase phase = event.phase;
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];

CGFloat eventScrollingDeltaX = event.scrollingDeltaX;
CGFloat eventScrollingDeltaY = event.scrollingDeltaY;
Expand Down Expand Up @@ -366,12 +366,40 @@ - (void)scrollWheel:(NSEvent *)event
scrollingDeltaY = 0;
dx = [event scrollingDeltaX];
dy = [event scrollingDeltaY];

if ([ud boolForKey:MMMouseWheelDisableAccelerationKey]) {
// Use scroll wheel as discrete steps as macOS acceleration often
// leads to unintuitive results.
NSInteger numLines = [ud integerForKey:MMMouseWheelNumLinesKey];
dx = dx == 0 ? 0 : (dx > 0 ? numLines : -numLines);
dy = dy == 0 ? 0 : (dy > 0 ? numLines : -numLines);
} else {
// Use the default OS acceleration, but we still want to round up
// the delta to at least 1 (configurable) as otherwise it's
// frustrating to use as MacVim fails to scroll even one line.
NSInteger minScrollLines = [ud integerForKey:MMMouseWheelMinLinesKey];
dx = dx == 0 ? 0 : (fabs(dx) > minScrollLines ? dx : (dx > 0 ? minScrollLines : -minScrollLines));
dy = dy == 0 ? 0 : (fabs(dy) > minScrollLines ? dy : (dy > 0 ? minScrollLines : -minScrollLines));
}

if ((*eventFlags & NSEventModifierFlagShift) && dx != 0 && dy == 0) {
// A shift-scroll in macOS converts a normal Y to X-axis scroll.
// There is no proper API to query this so this is just done by
// heuristics. We need to remove the shift flag, or Vim would see
// this as a <S-ScrollWheelRight> which is not what we want.
*eventFlags = *eventFlags & (~NSEventModifierFlagShift);
}
}
#else
dx = [event deltaX];
dy = [event deltaY];
#endif

*x = dx;
*y = dy;
}

- (void)scrollWheel:(NSEvent *)event
{
NSEventModifierFlags eventFlags = event.modifierFlags;
float dx = 0, dy = 0;
[self calcScrollWheelDeltas:event x:&dx y:&dy eventFlags:&eventFlags];
if (dx == 0 && dy == 0)
return;

Expand All @@ -386,7 +414,7 @@ - (void)scrollWheel:(NSEvent *)event
int row, col;
NSPoint pt = [textView convertPoint:[event locationInWindow] fromView:nil];
if ([textView convertPoint:pt toRow:&row column:&col]) {
unsigned flags = (unsigned)[event modifierFlags];
unsigned flags = (unsigned)eventFlags;
NSMutableData *data = [NSMutableData data];

[data appendBytes:&row length:sizeof(int)];
Expand Down
5 changes: 4 additions & 1 deletion src/MacVim/Miscellaneous.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ extern NSString *MMUseInlineImKey;
extern NSString *MMSuppressTerminationAlertKey;
extern NSString *MMNativeFullScreenKey;
extern NSString *MMUseMouseTimeKey;
extern NSString *MMMouseWheelDisableAccelerationKey; ///< Disable native macOS mouse scroll wheel acceleration
extern NSString *MMMouseWheelMinLinesKey; ///< Minimum scroll delta for mouse scroll wheel, only when acceleration is on
extern NSString *MMMouseWheelNumLinesKey; ///< Number of lines to scroll using mouse scroll wheel, only when acceleration is off
extern NSString *MMFullScreenFadeTimeKey;
extern NSString *MMNonNativeFullScreenShowMenuKey;
extern NSString *MMNonNativeFullScreenSafeAreaBehaviorKey;
Expand All @@ -69,7 +72,7 @@ extern NSString *MMCmdLineAlignBottomKey;
extern NSString *MMRendererClipToRowKey;
extern NSString *MMAllowForceClickLookUpKey;
extern NSString *MMUpdaterPrereleaseChannelKey;
extern NSString *MMLastUsedBundleVersionKey; // The last used version of MacVim before this launch
extern NSString *MMLastUsedBundleVersionKey; ///< The last used version of MacVim before this launch
extern NSString *MMShowWhatsNewOnStartupKey;
extern NSString *MMScrollOneDirectionOnlyKey;

Expand Down
3 changes: 3 additions & 0 deletions src/MacVim/Miscellaneous.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
NSString *MMSuppressTerminationAlertKey = @"MMSuppressTerminationAlert";
NSString *MMNativeFullScreenKey = @"MMNativeFullScreen";
NSString *MMUseMouseTimeKey = @"MMUseMouseTime";
NSString *MMMouseWheelDisableAccelerationKey = @"MMMouseWheelDisbleAcceleration";
NSString *MMMouseWheelMinLinesKey = @"MMMouseWheelMinLines";
NSString *MMMouseWheelNumLinesKey = @"MMMouseWheelNumLines";
NSString *MMFullScreenFadeTimeKey = @"MMFullScreenFadeTime";
NSString *MMNonNativeFullScreenShowMenuKey = @"MMNonNativeFullScreenShowMenu";
NSString *MMNonNativeFullScreenSafeAreaBehaviorKey = @"MMNonNativeFullScreenSafeAreaBehavior";
Expand Down
Loading