From 8e767891198309cd9790c6a068bbd4ccc4edce33 Mon Sep 17 00:00:00 2001 From: Aaron Tulino Date: Wed, 24 Dec 2025 14:12:34 -0700 Subject: [PATCH] Fix touchpad scrolling behavior (#1146) * Fix touchpad scrolling behavior * Make touchpad scroll smoothly For a normal mouse wheel, adjusting by 5% per scroll makes sense. For a touchpad, however, it should adjust by the smallest increment possible for a smooth experience. --- .../DankBar/Widgets/ControlCenterButton.qml | 49 +++++++++++++++++-- quickshell/Modules/DankBar/Widgets/Media.qml | 27 ++++++++-- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/quickshell/Modules/DankBar/Widgets/ControlCenterButton.qml b/quickshell/Modules/DankBar/Widgets/ControlCenterButton.qml index decbd254..4fa51332 100644 --- a/quickshell/Modules/DankBar/Widgets/ControlCenterButton.qml +++ b/quickshell/Modules/DankBar/Widgets/ControlCenterButton.qml @@ -21,6 +21,10 @@ BasePill { property bool showMicIcon: widgetData?.showMicIcon !== undefined ? widgetData.showMicIcon : SettingsData.controlCenterShowMicIcon property bool showBatteryIcon: widgetData?.showBatteryIcon !== undefined ? widgetData.showBatteryIcon : SettingsData.controlCenterShowBatteryIcon property bool showPrinterIcon: widgetData?.showPrinterIcon !== undefined ? widgetData.showPrinterIcon : SettingsData.controlCenterShowPrinterIcon + property real touchpadThreshold: 100 + property real micAccumulator: 0 + property real volumeAccumulator: 0 + property real brightnessAccumulator: 0 Loader { active: root.showPrinterIcon @@ -116,8 +120,21 @@ BasePill { function handleVolumeWheel(delta) { if (!AudioService.sink?.audio) return; + + var step = 5; + const isMouseWheel = Math.abs(delta) >= 120 && (Math.abs(delta) % 120) === 0; + if (!isMouseWheel) { + step = 1; + volumeAccumulator += delta; + if (Math.abs(volumeAccumulator) < touchpadThreshold) + return; + + delta = volumeAccumulator; + volumeAccumulator = 0; + } + const currentVolume = AudioService.sink.audio.volume * 100; - const newVolume = delta > 0 ? Math.min(100, currentVolume + 5) : Math.max(0, currentVolume - 5); + const newVolume = delta > 0 ? Math.min(100, currentVolume + step) : Math.max(0, currentVolume - step); AudioService.sink.audio.muted = false; AudioService.sink.audio.volume = newVolume / 100; AudioService.playVolumeChangeSoundIfEnabled(); @@ -126,8 +143,21 @@ BasePill { function handleMicWheel(delta) { if (!AudioService.source?.audio) return; + + var step = 5; + const isMouseWheel = Math.abs(delta) >= 120 && (Math.abs(delta) % 120) === 0; + if (!isMouseWheel) { + step = 1; + micAccumulator += delta; + if (Math.abs(micAccumulator) < touchpadThreshold) + return; + + delta = micAccumulator; + micAccumulator = 0; + } + const currentVolume = AudioService.source.audio.volume * 100; - const newVolume = delta > 0 ? Math.min(100, currentVolume + 5) : Math.max(0, currentVolume - 5); + const newVolume = delta > 0 ? Math.min(100, currentVolume + step) : Math.max(0, currentVolume - step); AudioService.source.audio.muted = false; AudioService.source.audio.volume = newVolume / 100; } @@ -137,8 +167,21 @@ BasePill { if (!deviceName) { return; } + + var step = 5; + const isMouseWheel = Math.abs(delta) >= 120 && (Math.abs(delta) % 120) === 0; + if (!isMouseWheel) { + step = 1; + brightnessAccumulator += delta; + if (Math.abs(brightnessAccumulator) < touchpadThreshold) + return; + + delta = brightnessAccumulator; + brightnessAccumulator = 0; + } + const currentBrightness = DisplayService.getDeviceBrightness(deviceName); - const newBrightness = delta > 0 ? Math.min(100, currentBrightness + 5) : Math.max(1, currentBrightness - 5); + const newBrightness = delta > 0 ? Math.min(100, currentBrightness + step) : Math.max(1, currentBrightness - step); DisplayService.setBrightness(newBrightness, deviceName); } diff --git a/quickshell/Modules/DankBar/Widgets/Media.qml b/quickshell/Modules/DankBar/Widgets/Media.qml index 1e626e17..b3cb5edf 100644 --- a/quickshell/Modules/DankBar/Widgets/Media.qml +++ b/quickshell/Modules/DankBar/Widgets/Media.qml @@ -48,19 +48,36 @@ BasePill { return audioVizHeight + Theme.spacingXS + playButtonHeight; } + property real scrollAccumulatorY: 0 + property real touchpadThreshold: 100 + onWheel: function (wheelEvent) { wheelEvent.accepted = true; if (!usePlayerVolume) return; - const delta = wheelEvent.angleDelta.y; + const deltaY = wheelEvent.angleDelta.y; + const isMouseWheelY = Math.abs(deltaY) >= 120 && (Math.abs(deltaY) % 120) === 0; + const currentVolume = activePlayer.volume * 100; - let newVolume; - if (delta > 0) { - newVolume = Math.min(100, currentVolume + 5); + let newVolume = currentVolume; + if (isMouseWheelY) { + if (deltaY > 0) { + newVolume = Math.min(100, currentVolume + 5); + } else if (deltaY < 0) { + newVolume = Math.max(0, currentVolume - 5); + } } else { - newVolume = Math.max(0, currentVolume - 5); + scrollAccumulatorY += deltaY; + if (Math.abs(scrollAccumulatorY) >= touchpadThreshold) { + if (scrollAccumulatorY > 0) { + newVolume = Math.min(100, currentVolume + 1); + } else { + newVolume = Math.max(0, currentVolume - 1); + } + scrollAccumulatorY = 0; + } } activePlayer.volume = newVolume / 100;