Skip to content

Commit 45506d1

Browse files
committed
Fixed volume change with hi-res mice and touchpad scrolling
An angle of 15° is required for changing the volume — as with ordinary mice. Also, * Changing the volume by touchpad scrolling is fixed; and * Tooltip flickering on wheel rotation is prevented.
1 parent 38c8a8d commit 45506d1

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

plugin-volume/volumepopup.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <XdgIcon>
3333

34+
#include <QTimer>
3435
#include <QSlider>
3536
#include <QStyleOptionButton>
3637
#include <QPushButton>
@@ -47,7 +48,8 @@ VolumePopup::VolumePopup(QWidget* parent):
4748
QDialog(parent, Qt::Dialog | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint | Qt::Popup | Qt::X11BypassWindowManagerHint),
4849
m_pos(0,0),
4950
m_anchor(Qt::TopLeftCorner),
50-
m_device(nullptr)
51+
m_device(nullptr),
52+
mWheelTimer(new QTimer(this))
5153
{
5254
// Under some Wayland compositors, setting window flags in the c-tor of the base class
5355
// may not be enough for a correct positioning of the popup.
@@ -84,6 +86,15 @@ VolumePopup::VolumePopup(QWidget* parent):
8486
connect(m_mixerButton, &QPushButton::released, this, &VolumePopup::launchMixer);
8587
connect(m_volumeSlider, &QSlider::valueChanged, this, &VolumePopup::handleSliderValueChanged);
8688
connect(m_muteToggleButton, &QPushButton::clicked, this, &VolumePopup::handleMuteToggleClicked);
89+
90+
mWheelTimer->setSingleShot(true);
91+
mWheelTimer->setInterval(350); // "QStyle::SH_ToolTip_WakeUpDelay" is 700 by default
92+
connect(mWheelTimer, &QTimer::timeout, this, [this] {
93+
QTimer::singleShot(0, this, [this] {
94+
if (!QToolTip::isVisible())
95+
QToolTip::showText(QCursor::pos(), m_volumeSlider->toolTip());
96+
});
97+
});
8798
}
8899

89100
bool VolumePopup::event(QEvent *event)
@@ -127,7 +138,10 @@ void VolumePopup::handleSliderValueChanged(int value)
127138
return;
128139
// qDebug("VolumePopup::handleSliderValueChanged: %d\n", value);
129140
m_device->setVolume(value);
130-
QTimer::singleShot(0, this, [this] { QToolTip::showText(QCursor::pos(), m_volumeSlider->toolTip()); });
141+
QTimer::singleShot(0, this, [this] {
142+
if (!mWheelTimer->isActive()) // a wheel event immediately hides the tooltip
143+
QToolTip::showText(QCursor::pos(), m_volumeSlider->toolTip());
144+
});
131145
}
132146

133147
void VolumePopup::handleMuteToggleClicked()
@@ -197,8 +211,21 @@ void VolumePopup::openAt(QPoint pos, Qt::Corner anchor)
197211

198212
void VolumePopup::handleWheelEvent(QWheelEvent *event)
199213
{
200-
m_volumeSlider->setSliderPosition(m_volumeSlider->sliderPosition()
201-
+ (event->angleDelta().y() / QWheelEvent::DefaultDeltasPerStep * m_volumeSlider->singleStep()));
214+
static int _delta = 0; // for high-resolution mice and touchpad scrolling
215+
216+
int delta = event->angleDelta().y();
217+
if ((_delta ^ delta) < 0)
218+
_delta = delta; // the wheel direction is reversed
219+
else
220+
_delta += delta;
221+
if (qAbs(_delta) >= QWheelEvent::DefaultDeltasPerStep) {
222+
m_volumeSlider->setSliderPosition(m_volumeSlider->sliderPosition()
223+
+ (_delta / QWheelEvent::DefaultDeltasPerStep * m_volumeSlider->singleStep()));
224+
_delta = 0;
225+
}
226+
227+
// show the tooltip only after the wheel rotation is stopped
228+
mWheelTimer->start();
202229
}
203230

204231
void VolumePopup::setDevice(AudioDevice *device)

plugin-volume/volumepopup.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include <QDialog>
3232

33+
class QTimer;
3334
class QSlider;
3435
class QPushButton;
3536
class AudioDevice;
@@ -81,6 +82,7 @@ private slots:
8182
QPoint m_pos;
8283
Qt::Corner m_anchor;
8384
AudioDevice *m_device;
85+
QTimer *mWheelTimer; // for showing tooltip with high-resolution mice
8486
};
8587

8688
#endif // VOLUMEPOPUP_H

0 commit comments

Comments
 (0)