File indexing completed on 2024-11-10 04:57:08
0001 /* 0002 SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "shakedetector.h" 0008 0009 #include <cmath> 0010 0011 ShakeDetector::ShakeDetector() 0012 { 0013 } 0014 0015 quint64 ShakeDetector::interval() const 0016 { 0017 return m_interval; 0018 } 0019 0020 void ShakeDetector::setInterval(quint64 interval) 0021 { 0022 m_interval = interval; 0023 } 0024 0025 qreal ShakeDetector::sensitivity() const 0026 { 0027 return m_sensitivity; 0028 } 0029 0030 void ShakeDetector::setSensitivity(qreal sensitivity) 0031 { 0032 m_sensitivity = sensitivity; 0033 } 0034 0035 std::optional<qreal> ShakeDetector::update(QMouseEvent *event) 0036 { 0037 // Prune the old entries in the history. 0038 auto it = m_history.begin(); 0039 for (; it != m_history.end(); ++it) { 0040 if (event->timestamp() - it->timestamp < m_interval) { 0041 break; 0042 } 0043 } 0044 if (it != m_history.begin()) { 0045 m_history.erase(m_history.begin(), it); 0046 } 0047 0048 m_history.emplace_back(HistoryItem{ 0049 .position = event->localPos(), 0050 .timestamp = event->timestamp(), 0051 }); 0052 0053 qreal left = m_history[0].position.x(); 0054 qreal top = m_history[0].position.y(); 0055 qreal right = m_history[0].position.x(); 0056 qreal bottom = m_history[0].position.y(); 0057 qreal distance = 0; 0058 0059 for (size_t i = 1; i < m_history.size(); ++i) { 0060 // Compute the length of the mouse path. 0061 const qreal deltaX = m_history.at(i).position.x() - m_history.at(i - 1).position.x(); 0062 const qreal deltaY = m_history.at(i).position.y() - m_history.at(i - 1).position.y(); 0063 distance += std::sqrt(deltaX * deltaX + deltaY * deltaY); 0064 0065 // Compute the bounds of the mouse path. 0066 left = std::min(left, m_history.at(i).position.x()); 0067 top = std::min(top, m_history.at(i).position.y()); 0068 right = std::max(right, m_history.at(i).position.x()); 0069 bottom = std::max(bottom, m_history.at(i).position.y()); 0070 } 0071 0072 const qreal boundsWidth = right - left; 0073 const qreal boundsHeight = bottom - top; 0074 const qreal diagonal = std::sqrt(boundsWidth * boundsWidth + boundsHeight * boundsHeight); 0075 if (diagonal < 100) { 0076 return std::nullopt; 0077 } 0078 0079 const qreal shakeFactor = distance / diagonal; 0080 if (shakeFactor > m_sensitivity) { 0081 return shakeFactor - m_sensitivity; 0082 } 0083 0084 return std::nullopt; 0085 }