mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-14 23:34:01 -04:00
78 lines
2.3 KiB
QML
78 lines
2.3 KiB
QML
import QtQuick
|
|
import "../../DCommon/Common/WheelInput.js" as WheelInput
|
|
import "../../DCommon/Widgets/ScrollConstants.js" as Scroll
|
|
|
|
WheelHandler {
|
|
id: handler
|
|
|
|
property real travel: 0
|
|
property real drift: 0
|
|
property bool engaged: false
|
|
property real lastTime: 0
|
|
property var samples: []
|
|
readonly property Timer settle: Timer {
|
|
interval: NotificationMetrics.swipeWheelSettleMs
|
|
onTriggered: handler.finish()
|
|
}
|
|
|
|
signal began
|
|
signal moved(real travel)
|
|
signal ended(real velocity)
|
|
|
|
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
|
|
orientation: Qt.Horizontal
|
|
blocking: false
|
|
target: null
|
|
|
|
function velocity() {
|
|
if (samples.length < 2)
|
|
return 0;
|
|
const span = samples[samples.length - 1].time - samples[0].time;
|
|
if (span <= 0)
|
|
return 0;
|
|
const total = samples.reduce((sum, s) => sum + s.delta, 0);
|
|
return Math.max(-Scroll.maxMomentumVelocity, Math.min(Scroll.maxMomentumVelocity, total / span * 1000));
|
|
}
|
|
|
|
function finish() {
|
|
settle.stop();
|
|
const lifted = Date.now() - lastTime < Scroll.velocitySampleWindowMs;
|
|
const fling = lifted ? velocity() : 0;
|
|
travel = 0;
|
|
drift = 0;
|
|
samples = [];
|
|
if (!engaged)
|
|
return;
|
|
engaged = false;
|
|
ended(fling);
|
|
}
|
|
|
|
onWheel: event => {
|
|
if (!WheelInput.isTouchpad(event))
|
|
return;
|
|
const now = Date.now();
|
|
// Qt Wayland negates finger deltas; natural scrolling flips them back and reports inverted
|
|
const delta = (event.inverted ? event.pixelDelta.x : -event.pixelDelta.x) * Scroll.touchpadSpeed;
|
|
travel += delta;
|
|
drift += event.pixelDelta.y * Scroll.touchpadSpeed;
|
|
samples = samples.filter(s => now - s.time < Scroll.velocitySampleWindowMs).concat({
|
|
"delta": delta,
|
|
"time": now
|
|
});
|
|
lastTime = now;
|
|
settle.restart();
|
|
if (!engaged) {
|
|
if (Math.abs(travel) < NotificationMetrics.swipeWheelEngageDistance || Math.abs(travel) <= Math.abs(drift))
|
|
return;
|
|
engaged = true;
|
|
began();
|
|
}
|
|
moved(travel);
|
|
}
|
|
|
|
onActiveChanged: {
|
|
if (!active)
|
|
finish();
|
|
}
|
|
}
|