plugins/shakecursor: Make the cursor big enough upon the first shake

The current behavior is that the cursor size follows how hard or fast
the cursor is shaken. While this looks fancy, given the purpose of this
plugin, it should be possible to magnify the cursor as easy as possible
without interfering or false triggering.

This change implements a sort of a compromise. When the cursor is shaken
for the first time, the cursor is magnified by some certain scale factor.
Then every next shake magnifies the cursor further by a smaller amount.
wilder/Plasma/6.2
Vlad Zahorodnii 2 years ago
parent 8736e44e1a
commit 2ad896c71d
  1. 57
      src/plugins/shakecursor/shakecursor.cpp
  2. 12
      src/plugins/shakecursor/shakecursor.h
  3. 5
      src/plugins/shakecursor/shakecursorconfig.kcfg
  4. 9
      src/plugins/shakecursor/shakedetector.cpp
  5. 3
      src/plugins/shakecursor/shakedetector.h

@ -21,17 +21,11 @@ ShakeCursorEffect::ShakeCursorEffect()
{
input()->installInputEventSpy(this);
m_resetCursorScaleTimer.setSingleShot(true);
connect(&m_resetCursorScaleTimer, &QTimer::timeout, this, [this]() {
m_resetCursorScaleAnimation.setStartValue(m_cursorMagnification);
m_resetCursorScaleAnimation.setEndValue(1.0);
m_resetCursorScaleAnimation.setDuration(animationTime(150));
m_resetCursorScaleAnimation.setEasingCurve(QEasingCurve::InOutCubic);
m_resetCursorScaleAnimation.start();
});
m_deflateTimer.setSingleShot(true);
connect(&m_deflateTimer, &QTimer::timeout, this, &ShakeCursorEffect::deflate);
connect(&m_resetCursorScaleAnimation, &QVariantAnimation::valueChanged, this, [this]() {
magnify(m_resetCursorScaleAnimation.currentValue().toReal());
connect(&m_scaleAnimation, &QVariantAnimation::valueChanged, this, [this]() {
magnify(m_scaleAnimation.currentValue().toReal());
});
ShakeCursorConfig::instance(effects->config());
@ -59,9 +53,36 @@ void ShakeCursorEffect::reconfigure(ReconfigureFlags flags)
m_shakeDetector.setSensitivity(ShakeCursorConfig::sensitivity());
}
bool ShakeCursorEffect::isActive() const
void ShakeCursorEffect::inflate()
{
qreal magnification;
if (m_targetMagnification == 1.0) {
magnification = ShakeCursorConfig::magnification();
} else {
magnification = m_targetMagnification + ShakeCursorConfig::overMagnification();
}
animateTo(magnification);
}
void ShakeCursorEffect::deflate()
{
return m_cursorMagnification != 1.0;
animateTo(1.0);
}
void ShakeCursorEffect::animateTo(qreal magnification)
{
if (m_targetMagnification != magnification) {
m_scaleAnimation.stop();
m_scaleAnimation.setStartValue(m_currentMagnification);
m_scaleAnimation.setEndValue(magnification);
m_scaleAnimation.setDuration(animationTime(200));
m_scaleAnimation.setEasingCurve(QEasingCurve::InOutCubic);
m_scaleAnimation.start();
m_targetMagnification = magnification;
}
}
void ShakeCursorEffect::pointerEvent(MouseEvent *event)
@ -74,24 +95,22 @@ void ShakeCursorEffect::pointerEvent(MouseEvent *event)
return;
}
if (const auto shakeFactor = m_shakeDetector.update(event)) {
m_resetCursorScaleTimer.start(animationTime(2000));
m_resetCursorScaleAnimation.stop();
magnify(std::max(m_cursorMagnification, 1.0 + ShakeCursorConfig::magnification() * shakeFactor.value()));
if (m_shakeDetector.update(event)) {
inflate();
m_deflateTimer.start(animationTime(2000));
}
}
void ShakeCursorEffect::magnify(qreal magnification)
{
if (magnification == 1.0) {
m_cursorMagnification = 1.0;
m_currentMagnification = 1.0;
if (m_cursorItem) {
m_cursorItem.reset();
effects->showCursor();
}
} else {
m_cursorMagnification = magnification;
m_currentMagnification = magnification;
if (!m_cursorItem) {
effects->hideCursor();

@ -31,18 +31,22 @@ public:
void reconfigure(ReconfigureFlags flags) override;
void pointerEvent(MouseEvent *event) override;
bool isActive() const override;
private:
void magnify(qreal magnification);
QTimer m_resetCursorScaleTimer;
QVariantAnimation m_resetCursorScaleAnimation;
void inflate();
void deflate();
void animateTo(qreal magnification);
QTimer m_deflateTimer;
QVariantAnimation m_scaleAnimation;
ShakeDetector m_shakeDetector;
Cursor *m_cursor;
std::unique_ptr<CursorItem> m_cursorItem;
qreal m_cursorMagnification = 1.0;
qreal m_targetMagnification = 1.0;
qreal m_currentMagnification = 1.0;
};
} // namespace KWin

@ -12,7 +12,10 @@
<default>4</default>
</entry>
<entry name="Magnification" type="Double">
<default>2</default>
<default>3</default>
</entry>
<entry name="OverMagnification" type="Double">
<default>1</default>
</entry>
</group>
</kcfg>

@ -32,7 +32,7 @@ void ShakeDetector::setSensitivity(qreal sensitivity)
m_sensitivity = sensitivity;
}
std::optional<qreal> ShakeDetector::update(QMouseEvent *event)
bool ShakeDetector::update(QMouseEvent *event)
{
// Prune the old entries in the history.
auto it = m_history.begin();
@ -73,13 +73,14 @@ std::optional<qreal> ShakeDetector::update(QMouseEvent *event)
const qreal boundsHeight = bottom - top;
const qreal diagonal = std::sqrt(boundsWidth * boundsWidth + boundsHeight * boundsHeight);
if (diagonal < 100) {
return std::nullopt;
return false;
}
const qreal shakeFactor = distance / diagonal;
if (shakeFactor > m_sensitivity) {
return shakeFactor - m_sensitivity;
m_history.clear();
return true;
}
return std::nullopt;
return false;
}

@ -9,7 +9,6 @@
#include <QMouseEvent>
#include <deque>
#include <optional>
/**
* The ShakeDetector type provides a way to detect pointer shake gestures.
@ -23,7 +22,7 @@ class ShakeDetector
public:
ShakeDetector();
std::optional<qreal> update(QMouseEvent *event);
bool update(QMouseEvent *event);
quint64 interval() const;
void setInterval(quint64 interval);

Loading…
Cancel
Save