From 881463f0d4aa9bd92c5f31ad81fa6d8ad13deca9 Mon Sep 17 00:00:00 2001 From: Yee Cheng Chin Date: Wed, 11 Oct 2023 20:27:53 -0700 Subject: [PATCH] Add option to only scroll in one direction when using trackpad This will pin the scrolling direction to the one at the beginning of a trackpad scrolling gesture, which helps prevent horizontal drift when the user is simply trying to scroll vertically up and down. At the beginning of the next scroll gesture the scrolling direction will be reset. This is the same as Visual Studio Code's "Scroll Predominant Axis" setting. --- runtime/doc/gui_mac.txt | 7 ++--- runtime/doc/tags | 1 + src/MacVim/Base.lproj/Preferences.xib | 37 +++++++++++++++++++++---- src/MacVim/MMAppController.m | 1 + src/MacVim/MMTextViewHelper.h | 7 +++++ src/MacVim/MMTextViewHelper.m | 39 +++++++++++++++++++++++---- src/MacVim/Miscellaneous.h | 1 + src/MacVim/Miscellaneous.m | 11 ++++---- 8 files changed, 86 insertions(+), 18 deletions(-) diff --git a/runtime/doc/gui_mac.txt b/runtime/doc/gui_mac.txt index d6c08f2f83..d7a9d2fe72 100644 --- a/runtime/doc/gui_mac.txt +++ b/runtime/doc/gui_mac.txt @@ -260,9 +260,9 @@ The ODB editor protocol is documented at: 3. Settings *macvim-prefs* *macvim-preferences* *macvim-settings* Some settings are global to the MacVim application and would not make sense as -Vim options. These settings are stored in the user defaults database and can -be accessed via the "MacVim.Settings…" ("MacVim.Preferences…" in macOS 12 -Monterey and older) menu item. +Vim options (see |macvim-options|). These settings are stored in the user +defaults database and can be accessed via the "MacVim.Settings…" +("MacVim.Preferences…" in macOS 12 Monterey and older) menu item. *macvim-user-defaults* Not all entries in the user defaults database are exposed via the settings @@ -299,6 +299,7 @@ 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] *MMShowAddTabButton* enable "add tab" button on tabline [bool] diff --git a/runtime/doc/tags b/runtime/doc/tags index 8076be86a8..59e92bff48 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -5586,6 +5586,7 @@ MMNoTitleBarWindow gui_mac.txt /*MMNoTitleBarWindow* MMNonNativeFullScreenSafeAreaBehavior gui_mac.txt /*MMNonNativeFullScreenSafeAreaBehavior* MMNonNativeFullScreenShowMenu gui_mac.txt /*MMNonNativeFullScreenShowMenu* MMRendererClipToRow gui_mac.txt /*MMRendererClipToRow* +MMScrollOneDirectionOnly gui_mac.txt /*MMScrollOneDirectionOnly* MMShareFindPboard gui_mac.txt /*MMShareFindPboard* MMShowAddTabButton gui_mac.txt /*MMShowAddTabButton* MMShowWhatsNewOnStartup gui_mac.txt /*MMShowWhatsNewOnStartup* diff --git a/src/MacVim/Base.lproj/Preferences.xib b/src/MacVim/Base.lproj/Preferences.xib index 0ecc7b8278..ba62b25118 100644 --- a/src/MacVim/Base.lproj/Preferences.xib +++ b/src/MacVim/Base.lproj/Preferences.xib @@ -495,11 +495,11 @@ - + - + @@ -526,10 +526,10 @@ - + - + @@ -551,8 +551,35 @@ + + + + + + + + + + + + + + + + - + diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index 571efb5253..339c5bd279 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -268,6 +268,7 @@ + (void)initialize [NSNumber numberWithBool:NO], MMUpdaterPrereleaseChannelKey, @"", MMLastUsedBundleVersionKey, [NSNumber numberWithBool:YES], MMShowWhatsNewOnStartupKey, + [NSNumber numberWithBool:0], MMScrollOneDirectionOnlyKey, nil]; [[NSUserDefaults standardUserDefaults] registerDefaults:dict]; diff --git a/src/MacVim/MMTextViewHelper.h b/src/MacVim/MMTextViewHelper.h index 72518b40e7..3ae7f7e424 100644 --- a/src/MacVim/MMTextViewHelper.h +++ b/src/MacVim/MMTextViewHelper.h @@ -22,6 +22,12 @@ @interface MMTextViewHelper : NSObject { + enum ScrollingDirection { + ScrollingDirectionUnknown = 0, + ScrollingDirectionVertical, + ScrollingDirectionHorizontal, + }; + id textView; BOOL isDragging; int dragRow; @@ -38,6 +44,7 @@ NSDate *mouseDownTime; CGFloat scrollingDeltaX; CGFloat scrollingDeltaY; + enum ScrollingDirection scrollingDirection; ///< The fixed scrolling direction when using track pad (if configured to use it) // Input Manager NSRange imRange; diff --git a/src/MacVim/MMTextViewHelper.m b/src/MacVim/MMTextViewHelper.m index c196435c29..f2a350ee59 100644 --- a/src/MacVim/MMTextViewHelper.m +++ b/src/MacVim/MMTextViewHelper.m @@ -305,15 +305,44 @@ - (void)scrollWheel:(NSEvent *)event #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 if ([event hasPreciseScrollingDeltas]) { - NSSize cellSize = [textView cellSize]; - float thresholdX = cellSize.width; - float thresholdY = cellSize.height; - scrollingDeltaX += [event scrollingDeltaX]; + const NSEventPhase phase = event.phase; + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + CGFloat eventScrollingDeltaX = event.scrollingDeltaX; + CGFloat eventScrollingDeltaY = event.scrollingDeltaY; + + // If user wants to only scroll in one direction to prevent accidental + // side scroll, we lock that in at the beginning of a scroll gesture. + // Note that we choose Y if both X and Y deltas exist, because most of + // the time, the user is doing a vertical scroll. + if (phase == NSEventPhaseMayBegin || phase == NSEventPhaseBegan) { + scrollingDirection = ScrollingDirectionUnknown; + } + if (scrollingDirection == ScrollingDirectionUnknown) { + if (event.scrollingDeltaY != 0) { + scrollingDirection = ScrollingDirectionVertical; + } else if (event.scrollingDeltaX != 0) { + scrollingDirection = ScrollingDirectionHorizontal; + } + } + if ([ud boolForKey:MMScrollOneDirectionOnlyKey]) { + if (scrollingDirection == ScrollingDirectionVertical) { + eventScrollingDeltaX = 0; + } else if (scrollingDirection == ScrollingDirectionHorizontal) { + eventScrollingDeltaY = 0; + } + } + + const NSSize cellSize = [textView cellSize]; + const float thresholdX = cellSize.width; + const float thresholdY = cellSize.height; + + scrollingDeltaX += eventScrollingDeltaX; if (fabs(scrollingDeltaX) > thresholdX) { dx = roundf(scrollingDeltaX / thresholdX); scrollingDeltaX -= thresholdX * dx; } - scrollingDeltaY += [event scrollingDeltaY]; + scrollingDeltaY += eventScrollingDeltaY; if (fabs(scrollingDeltaY) > thresholdY) { dy = roundf(scrollingDeltaY / thresholdY); scrollingDeltaY -= thresholdY * dy; diff --git a/src/MacVim/Miscellaneous.h b/src/MacVim/Miscellaneous.h index dec2a5adea..0e00adf94f 100644 --- a/src/MacVim/Miscellaneous.h +++ b/src/MacVim/Miscellaneous.h @@ -66,6 +66,7 @@ extern NSString *MMAllowForceClickLookUpKey; extern NSString *MMUpdaterPrereleaseChannelKey; extern NSString *MMLastUsedBundleVersionKey; // The last used version of MacVim before this launch extern NSString *MMShowWhatsNewOnStartupKey; +extern NSString *MMScrollOneDirectionOnlyKey; // Enum for MMUntitledWindowKey diff --git a/src/MacVim/Miscellaneous.m b/src/MacVim/Miscellaneous.m index 0718755183..f889fd74e8 100644 --- a/src/MacVim/Miscellaneous.m +++ b/src/MacVim/Miscellaneous.m @@ -53,15 +53,16 @@ NSString *MMNativeFullScreenKey = @"MMNativeFullScreen"; NSString *MMUseMouseTimeKey = @"MMUseMouseTime"; NSString *MMFullScreenFadeTimeKey = @"MMFullScreenFadeTime"; -NSString *MMNonNativeFullScreenShowMenuKey = @"MMNonNativeFullScreenShowMenu"; -NSString *MMNonNativeFullScreenSafeAreaBehaviorKey = @"MMNonNativeFullScreenSafeAreaBehavior"; +NSString *MMNonNativeFullScreenShowMenuKey = @"MMNonNativeFullScreenShowMenu"; +NSString *MMNonNativeFullScreenSafeAreaBehaviorKey = @"MMNonNativeFullScreenSafeAreaBehavior"; NSString *MMSmoothResizeKey = @"MMSmoothResize"; NSString *MMCmdLineAlignBottomKey = @"MMCmdLineAlignBottom"; -NSString *MMRendererClipToRowKey = @"MMRendererClipToRow"; +NSString *MMRendererClipToRowKey = @"MMRendererClipToRow"; NSString *MMAllowForceClickLookUpKey = @"MMAllowForceClickLookUp"; NSString *MMUpdaterPrereleaseChannelKey = @"MMUpdaterPrereleaseChannel"; -NSString *MMLastUsedBundleVersionKey = @"MMLastUsedBundleVersion"; -NSString *MMShowWhatsNewOnStartupKey = @"MMShowWhatsNewOnStartup"; +NSString *MMLastUsedBundleVersionKey = @"MMLastUsedBundleVersion"; +NSString *MMShowWhatsNewOnStartupKey = @"MMShowWhatsNewOnStartup"; +NSString *MMScrollOneDirectionOnlyKey = @"MMScrollOneDirectionOnly"; @implementation NSIndexSet (MMExtras)