Fix #5194: Fix knobs moving too fast (#5360)

This PR fixes issues on systems where `QCursor::setPos()` has no effect
or is not reliable. These issues included knobs moving to fast on some
operating systems. Affected widgets are `Knob` and `LcdSpinBox`.

With this PR, on all operating systems, the `setPos` calls are removed and
the cursor is not hidden anymore, so the mouse keeps moving normally
when changing values of one of the widgets.

As now the previous pointer position keeps moving (instead of being reset
to the original position using `QCursor::setPos`), the mathematics that
translate pointer pixel distance to `Knob`/`LcdSpinBox` value increase
have to be changed:

* The `Knob` transition function is now linear and uses a new factor.
* `LcdSpinBox` now uses float values and saves the current float remainder
  (this is actually a separate issue revealed by this fix), leading to a fluent,
  non hanging movement.
This commit is contained in:
Johannes Lorenz
2020-05-24 13:35:16 +02:00
committed by GitHub
parent 3a985ff1fc
commit c6a1abe150
4 changed files with 29 additions and 28 deletions

View File

@@ -497,8 +497,8 @@ float Knob::getValue( const QPoint & _p )
{
float value;
// arcane mathemagicks for calculating knob movement
value = ( ( _p.y() + _p.y() * qMin( qAbs( _p.y() / 2.5f ), 6.0f ) ) ) / 12.0f;
// knob value increase is linear to mouse movement
value = .4f * _p.y();
// if shift pressed we want slower movement
if( gui->mainWindow()->isShiftPressed() )
@@ -587,13 +587,11 @@ void Knob::mousePressEvent( QMouseEvent * _me )
}
const QPoint & p = _me->pos();
m_origMousePos = p;
m_mouseOffset = QPoint(0, 0);
m_lastMousePos = p;
m_leftOver = 0.0f;
emit sliderPressed();
QApplication::setOverrideCursor( Qt::BlankCursor );
s_textFloat->setText( displayValue() );
s_textFloat->moveGlobal( this,
QPoint( width() + 2, 0 ) );
@@ -618,12 +616,13 @@ void Knob::mousePressEvent( QMouseEvent * _me )
void Knob::mouseMoveEvent( QMouseEvent * _me )
{
if( m_buttonPressed && _me->pos() != m_origMousePos )
if( m_buttonPressed && _me->pos() != m_lastMousePos )
{
m_mouseOffset = _me->pos() - m_origMousePos;
setPosition( m_mouseOffset );
// knob position is changed depending on last mouse position
setPosition( _me->pos() - m_lastMousePos );
emit sliderMoved( model()->value() );
QCursor::setPos( mapToGlobal( m_origMousePos ) );
// original position for next time is current position
m_lastMousePos = _me->pos();
}
s_textFloat->setText( displayValue() );
}

View File

@@ -23,6 +23,7 @@
*
*/
#include <cmath>
#include <QApplication>
#include <QLabel>
#include <QMouseEvent>
@@ -40,8 +41,9 @@
LcdSpinBox::LcdSpinBox( int numDigits, QWidget* parent, const QString& name ) :
LcdWidget( numDigits, parent, name ),
IntModelView( new IntModel( 0, 0, 0, NULL, name, true ), this ),
m_remainder( 0.f ),
m_mouseMoving( false ),
m_origMousePos(),
m_lastMousePos(),
m_displayOffset( 0 )
{
}
@@ -52,8 +54,9 @@ LcdSpinBox::LcdSpinBox( int numDigits, QWidget* parent, const QString& name ) :
LcdSpinBox::LcdSpinBox( int numDigits, const QString& style, QWidget* parent, const QString& name ) :
LcdWidget( numDigits, parent, name ),
IntModelView( new IntModel( 0, 0, 0, NULL, name, true ), this ),
m_remainder( 0.f ),
m_mouseMoving( false ),
m_origMousePos(),
m_lastMousePos(),
m_displayOffset( 0 )
{
}
@@ -98,8 +101,7 @@ void LcdSpinBox::mousePressEvent( QMouseEvent* event )
event->y() < cellHeight() + 2 )
{
m_mouseMoving = true;
m_origMousePos = event->globalPos();
QApplication::setOverrideCursor( Qt::BlankCursor );
m_lastMousePos = event->globalPos();
AutomatableModel *thisModel = model();
if( thisModel )
@@ -121,15 +123,20 @@ void LcdSpinBox::mouseMoveEvent( QMouseEvent* event )
{
if( m_mouseMoving )
{
int dy = event->globalY() - m_origMousePos.y();
if( event->modifiers() & Qt::ShiftModifier )
dy = qBound( -4, dy/4, 4 );
if( dy > 1 || dy < -1 )
int dy = event->globalY() - m_lastMousePos.y();
if( dy )
{
model()->setInitValue( model()->value() -
dy / 2 * model()->step<int>() );
float fdy = static_cast<float>(dy);
if( event->modifiers() & Qt::ShiftModifier ) {
fdy = qBound( -4.f, fdy/4.f, 4.f );
}
float floatValNotRounded =
model()->value() + m_remainder - fdy / 2.f * model()->step<int>();
float floatValRounded = roundf( floatValNotRounded );
m_remainder = floatValNotRounded - floatValRounded;
model()->setInitValue( floatValRounded );
emit manualChange();
QCursor::setPos( m_origMousePos );
m_lastMousePos = event->globalPos();
}
}
}
@@ -142,10 +149,7 @@ void LcdSpinBox::mouseReleaseEvent( QMouseEvent* )
if( m_mouseMoving )
{
model()->restoreJournallingState();
QCursor::setPos( m_origMousePos );
QApplication::restoreOverrideCursor();
m_mouseMoving = false;
}
}
@@ -187,5 +191,3 @@ void LcdSpinBox::enterValue()
}
}