diff --git a/resources/l10n/Localizable.strings b/resources/l10n/Localizable.strings index cf3caae6..267e4afe 100644 --- a/resources/l10n/Localizable.strings +++ b/resources/l10n/Localizable.strings @@ -526,6 +526,9 @@ /* No comment provided by engineer. */ "Titles" = "Titles"; +/* No comment provided by engineer. */ +"Trackpad haptic feedback" = "Trackpad haptic feedback"; + /* No comment provided by engineer. */ "Trigger shortcut" = "Trigger shortcut"; diff --git a/src/logic/Preferences.swift b/src/logic/Preferences.swift index 6ead5706..fca6e44b 100644 --- a/src/logic/Preferences.swift +++ b/src/logic/Preferences.swift @@ -87,6 +87,7 @@ class Preferences { "hideThumbnails": "false", "previewFocusedWindow": "false", "screenRecordingPermissionSkipped": "false", + "trackpadHapticFeedbackEnabled": "true", ] // system preferences @@ -110,6 +111,7 @@ class Preferences { static var vimKeysEnabled: Bool { CachedUserDefaults.bool("vimKeysEnabled") } static var mouseHoverEnabled: Bool { CachedUserDefaults.bool("mouseHoverEnabled") } static var cursorFollowFocus: CursorFollowFocus { CachedUserDefaults.macroPref("cursorFollowFocus", CursorFollowFocus.allCases) } + static var trackpadHapticFeedbackEnabled: Bool { CachedUserDefaults.bool("trackpadHapticFeedbackEnabled") } static var showTabsAsWindows: Bool { CachedUserDefaults.bool("showTabsAsWindows") } static var hideColoredCircles: Bool { CachedUserDefaults.bool("hideColoredCircles") } static var windowDisplayDelay: DispatchTimeInterval { DispatchTimeInterval.milliseconds(CachedUserDefaults.int("windowDisplayDelay")) } diff --git a/src/logic/events/TrackpadEvents.swift b/src/logic/events/TrackpadEvents.swift index d9429b47..66ff30f0 100644 --- a/src/logic/events/TrackpadEvents.swift +++ b/src/logic/events/TrackpadEvents.swift @@ -157,6 +157,7 @@ class TriggerSwipeDetector { reset() DispatchQueue.main.async { ScrollwheelEvents.toggle(true) + performHapticFeedback() App.app.showUiOrCycleSelection(Preferences.gestureIndex, false) } return true @@ -187,7 +188,10 @@ class NavigationSwipeDetector { if (maxIsX ? absX : absY) > MIN_SWIPE_DISTANCE { maxIsX ? resetX(activeTouches) : resetY(activeTouches) let direction: Direction = maxIsX ? (averageDistance.x < 0 ? .left : .right) : (averageDistance.y < 0 ? .down : .up) - DispatchQueue.main.async { App.app.cycleSelection(direction, allowWrap: false) } + DispatchQueue.main.async { + performHapticFeedback() + App.app.cycleSelection(direction, allowWrap: false) + } return true } return nil @@ -209,3 +213,9 @@ class NavigationSwipeDetector { } } } + +func performHapticFeedback() { + if Preferences.trackpadHapticFeedbackEnabled { + NSHapticFeedbackManager.defaultPerformer.perform(.generic, performanceTime: .default) + } +} diff --git a/src/ui/preferences-window/tabs/controls/AdditionalControlsSheet.swift b/src/ui/preferences-window/tabs/controls/AdditionalControlsSheet.swift index 1ffe6097..5a308d31 100644 --- a/src/ui/preferences-window/tabs/controls/AdditionalControlsSheet.swift +++ b/src/ui/preferences-window/tabs/controls/AdditionalControlsSheet.swift @@ -10,6 +10,8 @@ class AdditionalControlsSheet: SheetWindow { rightViews: [LabelAndControl.makeSwitch("mouseHoverEnabled")]) let enableCursorFollowFocus = TableGroupView.Row(leftTitle: NSLocalizedString("Cursor follows focus", comment: ""), rightViews: [LabelAndControl.makeDropdown("cursorFollowFocus", CursorFollowFocus.allCases)]) + let enableTrackpadHapticFeedback = TableGroupView.Row(leftTitle: NSLocalizedString("Trackpad haptic feedback", comment: ""), + rightViews: [LabelAndControl.makeSwitch("trackpadHapticFeedbackEnabled")]) ControlsTab.arrowKeysCheckbox = enableArrows.rightViews[0] as? Switch ControlsTab.vimKeysCheckbox = enableVimKeys.rightViews[0] as? Switch ControlsTab.arrowKeysEnabledCallback(ControlsTab.arrowKeysCheckbox) @@ -22,6 +24,7 @@ class AdditionalControlsSheet: SheetWindow { let table2 = TableGroupView(title: NSLocalizedString("Miscellaneous", comment: ""), width: PreferencesWindow.width) _ = table2.addRow(enableCursorFollowFocus) + _ = table2.addRow(enableTrackpadHapticFeedback) let view = TableGroupSetView(originalViews: [table1, table2], padding: 0) return view }