diff options
author | Marc Mondesir <timepilot3000@gmail.com> | 2024-10-25 11:40:46 -0700 |
---|---|---|
committer | Patrick Luby <guibomacdev@gmail.com> | 2024-10-30 15:04:17 +0100 |
commit | f9e2bc8d84fe729d7a501dc3acc6325e246f0b7d (patch) | |
tree | c13496f6fe19eaa97ce95157a294a69725403b09 | |
parent | f69980d036b3f388982d7b1b2907cc165ee04b52 (diff) |
tdf#163582: Fix scrolling distance increasing geometrically.
New scroll distance was previous distance multiplied by speed factor, but distance was not reset to base values when mouse not moved (or outside app window on some platforms), resulting in continuous multiply amplification. Break out base scroll values to separate variables to prevent multiply feedback. Add comments to help future code maintenance.
Change-Id: If11baff3b25521abce7436b44aaf8e6a19e54f45
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175657
Tested-by: Jenkins
Reviewed-by: Patrick Luby <guibomacdev@gmail.com>
-rw-r--r-- | vcl/inc/scrwnd.hxx | 6 | ||||
-rw-r--r-- | vcl/source/window/scrwnd.cxx | 59 |
2 files changed, 42 insertions, 23 deletions
diff --git a/vcl/inc/scrwnd.hxx b/vcl/inc/scrwnd.hxx index f92ebe556cfb..2f57b31d384e 100644 --- a/vcl/inc/scrwnd.hxx +++ b/vcl/inc/scrwnd.hxx @@ -52,8 +52,10 @@ private: WheelMode mnWheelMode; sal_uLong mnMaxWidth; sal_uLong mnActDist; - tools::Long mnActDeltaX; - tools::Long mnActDeltaY; + tools::Long mnStepDeltaX; // x component of scroll direction + tools::Long mnStepDeltaY; // y component of scroll direction + tools::Long mnActDeltaX; // x component of scroll distance + tools::Long mnActDeltaY; // y component of scroll distance void ImplCreateImageList(); void ImplSetRegion(const Bitmap& rRegionBmp); using Window::ImplGetMousePointer; diff --git a/vcl/source/window/scrwnd.cxx b/vcl/source/window/scrwnd.cxx index 511d60fc2ca5..8634dc2332db 100644 --- a/vcl/source/window/scrwnd.cxx +++ b/vcl/source/window/scrwnd.cxx @@ -46,6 +46,8 @@ ImplWheelWindow::ImplWheelWindow( vcl::Window* pParent ) : mnTimeout ( DEF_TIMEOUT ), mnWheelMode ( WheelMode::NONE ), mnActDist ( 0 ), + mnStepDeltaX ( 0 ), + mnStepDeltaY ( 0 ), mnActDeltaX ( 0 ), mnActDeltaY ( 0 ) { @@ -189,11 +191,12 @@ void ImplWheelWindow::ImplRecalcScrollValues() } else { - sal_uInt64 nCurTime; + sal_uInt64 nCurTime; // Scrolling time interval // calc current time if( mnMaxWidth ) { + // Time interval for each unit of scrolling. Mouse further from start point -> shorter time interval -> faster scrolling. const double fExp = ( static_cast<double>(mnActDist) / mnMaxWidth ) * log10( double(MAX_TIME) / MIN_TIME ); nCurTime = static_cast<sal_uInt64>( MAX_TIME / pow( 10., fExp ) ); } @@ -203,19 +206,23 @@ void ImplWheelWindow::ImplRecalcScrollValues() if( !nCurTime ) nCurTime = 1; - if( mnRepaintTime <= nCurTime ) - mnTimeout = nCurTime - mnRepaintTime; - else + if( mnRepaintTime <= nCurTime ) // Draw time less than scroll time interval + { + mnActDeltaX = mnStepDeltaX; // Scroll 1 unit + mnActDeltaY = mnStepDeltaY; + mnTimeout = nCurTime - mnRepaintTime; // Call handler again after remaining interval elapsed + } + else // Draw time greater than scroll time { - sal_uInt64 nMult = mnRepaintTime / nCurTime; + sal_uInt64 nMult = mnRepaintTime / nCurTime; // Scroll # units based on how many scroll intervals elapsed if( !( mnRepaintTime % nCurTime ) ) mnTimeout = 0; else mnTimeout = ++nMult * nCurTime - mnRepaintTime; - double fValX = static_cast<double>(mnActDeltaX) * nMult; - double fValY = static_cast<double>(mnActDeltaY) * nMult; + double fValX = static_cast<double>(mnStepDeltaX) * nMult; // Get scroll distance from # units * step + double fValY = static_cast<double>(mnStepDeltaY) * nMult; mnActDeltaX = o3tl::saturating_cast<tools::Long>(fValX); mnActDeltaY = o3tl::saturating_cast<tools::Long>(fValY); @@ -308,23 +315,32 @@ void ImplWheelWindow::MouseMove( const MouseEvent& rMEvt ) const StartAutoScrollFlags nFlags = ImplGetSVData()->mpWinData->mnAutoScrollFlags; const bool bHorz( nFlags & StartAutoScrollFlags::Horz ); const bool bVert( nFlags & StartAutoScrollFlags::Vert ); - const bool bOuter = mnActDist > WHEEL_RADIUS; + const bool bOuter = mnActDist > WHEEL_RADIUS; // More than minimum distance from start point? - if( bOuter && ( maLastMousePos != aMousePos ) ) + if( maLastMousePos != aMousePos ) { - switch( eActStyle ) + if( bOuter ) // More than minimum distance + { + switch( eActStyle ) + { + case PointerStyle::AutoScrollN: mnStepDeltaX = +0; mnStepDeltaY = +1; break; + case PointerStyle::AutoScrollS: mnStepDeltaX = +0; mnStepDeltaY = -1; break; + case PointerStyle::AutoScrollW: mnStepDeltaX = +1; mnStepDeltaY = +0; break; + case PointerStyle::AutoScrollE: mnStepDeltaX = -1; mnStepDeltaY = +0; break; + case PointerStyle::AutoScrollNW: mnStepDeltaX = +1; mnStepDeltaY = +1; break; + case PointerStyle::AutoScrollNE: mnStepDeltaX = -1; mnStepDeltaY = +1; break; + case PointerStyle::AutoScrollSW: mnStepDeltaX = +1; mnStepDeltaY = -1; break; + case PointerStyle::AutoScrollSE: mnStepDeltaX = -1; mnStepDeltaY = -1; break; + + default: + mnStepDeltaX = 0; mnStepDeltaY = 0; + break; + } + } + else // Less than minimum distance { - case PointerStyle::AutoScrollN: mnActDeltaX = +0; mnActDeltaY = +1; break; - case PointerStyle::AutoScrollS: mnActDeltaX = +0; mnActDeltaY = -1; break; - case PointerStyle::AutoScrollW: mnActDeltaX = +1; mnActDeltaY = +0; break; - case PointerStyle::AutoScrollE: mnActDeltaX = -1; mnActDeltaY = +0; break; - case PointerStyle::AutoScrollNW: mnActDeltaX = +1; mnActDeltaY = +1; break; - case PointerStyle::AutoScrollNE: mnActDeltaX = -1; mnActDeltaY = +1; break; - case PointerStyle::AutoScrollSW: mnActDeltaX = +1; mnActDeltaY = -1; break; - case PointerStyle::AutoScrollSE: mnActDeltaX = -1; mnActDeltaY = -1; break; - - default: - break; + mnStepDeltaX = 0; + mnStepDeltaY = 0; } } @@ -371,6 +387,7 @@ IMPL_LINK_NOARG(ImplWheelWindow, ImplScrollHdl, Timer *, void) } } + // Call this handler again based on scrolling time interval if ( mnTimeout != mpTimer->GetTimeout() ) mpTimer->SetTimeout( mnTimeout ); mpTimer->Start(); |