vcl/inc/window.h              |    2 ++
 vcl/source/window/window.cxx  |    2 ++
 vcl/source/window/window2.cxx |   37 ++++++++++++++++++++++---------------
 3 files changed, 26 insertions(+), 15 deletions(-)

New commits:
commit fe21365c5a9083ae1f086ea48614263b3a75ab3e
Author:     Jonas Eyov <je...@proton.me>
AuthorDate: Fri Nov 18 03:40:57 2022 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Mon Nov 21 17:28:45 2022 +0100

    tdf#143209 vcl: track partial scroll deltas
    
    this makes scrolling in calc smoother and makes left/up scrolling
    the same speed as right/down scrolling, which was previously not the
    case.
    
    prior to this change, Window::HandleScrollCommand only checked each
    event for being a large enough scroll to advance one unit. this
    happened in lcl_HandleScrollHelper by way of o3tl::saturating_cast,
    which meant that nonzero upward/leftward scrolls were always worth at
    least one unit, while downward/rightward scrolls needed to be larger
    than 1 to count.
    
    now, we accumulate partial scroll offsets in WindowImpl and perform a
    saturating cast on the absolute value, so behavior is symmetric and
    sensitive to accumulated small scroll values. this feels smoother
    and is more correct.
    
    Change-Id: Id3692d14edd45ed26f2952e3418e4d82806e1fc4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142948
    Tested-by: Jenkins
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index 639bee80e82c..6f10445abf39 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -256,6 +256,8 @@ public:
     vcl::Cursor*        mpCursor;
     PointerStyle        maPointer;
     Fraction            maZoom;
+    double              mfPartialScrollX;
+    double              mfPartialScrollY;
     OUString            maText;
     std::optional<vcl::Font>
                         mpControlFont;
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 4705fe516ce5..5cfc50d717c0 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -590,6 +590,8 @@ WindowImpl::WindowImpl( vcl::Window& rWindow, WindowType 
nType )
 {
     mxOutDev = VclPtr<vcl::WindowOutputDevice>::Create(rWindow);
     maZoom                              = Fraction( 1, 1 );
+    mfPartialScrollX                    = 0.0;
+    mfPartialScrollY                    = 0.0;
     maWinRegion                         = vcl::Region(true);
     maWinClipRegion                     = vcl::Region(true);
     mpWinData                           = nullptr;                      // 
Extra Window Data, that we don't need for all windows
diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
index b6c4ee25415a..978dc0b6ecf8 100644
--- a/vcl/source/window/window2.cxx
+++ b/vcl/source/window/window2.cxx
@@ -598,12 +598,14 @@ tools::Long Window::GetDrawPixel( OutputDevice const * 
pDev, tools::Long nPixels
     return nP;
 }
 
-static void lcl_HandleScrollHelper( Scrollable* pScrl, double nN, bool 
isMultiplyByLineSize )
+// returns how much was actually scrolled (so that abs(retval) <= abs(nN))
+static double lcl_HandleScrollHelper( Scrollable* pScrl, double nN, bool 
isMultiplyByLineSize )
 {
     if (!pScrl || !nN || pScrl->Inactive())
-        return;
+        return 0.0;
 
     tools::Long nNewPos = pScrl->GetThumbPos();
+    double scrolled = nN;
 
     if ( nN == double(-LONG_MAX) )
         nNewPos += pScrl->GetPageSize();
@@ -616,13 +618,22 @@ static void lcl_HandleScrollHelper( Scrollable* pScrl, 
double nN, bool isMultipl
             nN*=pScrl->GetLineSize();
         }
 
-        const double fVal = nNewPos - nN;
+        // compute how many quantized units to scroll
+        tools::Long magnitude = o3tl::saturating_cast<tools::Long>(abs(nN));
+        tools::Long change = copysign(magnitude, nN);
+
+        nNewPos = nNewPos - change;
 
-        nNewPos = o3tl::saturating_cast<tools::Long>(fVal);
+        scrolled = double(change);
+        // convert back to chunked/continuous
+        if(isMultiplyByLineSize){
+            scrolled /= pScrl->GetLineSize();
+        }
     }
 
     pScrl->DoScroll( nNewPos );
 
+    return scrolled;
 }
 
 bool Window::HandleScrollCommand( const CommandEvent& rCmd,
@@ -668,6 +679,9 @@ bool Window::HandleScrollCommand( const CommandEvent& rCmd,
                     {
                         double nScrollLines = pData->GetScrollLines();
                         double nLines;
+                        double* partialScroll = pData->IsHorz()
+                            ? &mpWindowImpl->mfPartialScrollX
+                            : &mpWindowImpl->mfPartialScrollY;
                         if ( nScrollLines == COMMAND_WHEEL_PAGESCROLL )
                         {
                             if ( pData->GetDelta() < 0 )
@@ -676,13 +690,12 @@ bool Window::HandleScrollCommand( const CommandEvent& 
rCmd,
                                 nLines = double(LONG_MAX);
                         }
                         else
-                            nLines = pData->GetNotchDelta() * nScrollLines;
+                            nLines = *partialScroll + pData->GetNotchDelta() * 
nScrollLines;
                         if ( nLines )
                         {
-                            ImplHandleScroll( nullptr,
-                                          0L,
-                                          pData->IsHorz() ? pHScrl : pVScrl,
-                                          nLines );
+                            Scrollable* pScrl = pData->IsHorz() ? pHScrl : 
pVScrl;
+                            double scrolled = lcl_HandleScrollHelper( pScrl, 
nLines, true );
+                            *partialScroll = nLines - scrolled;
                             bRet = true;
                         }
                     }
@@ -806,12 +819,6 @@ bool Window::HandleScrollCommand( const CommandEvent& rCmd,
     return bRet;
 }
 
-// Note that when called for CommandEventId::Wheel above, despite its name,
-// pVScrl isn't necessarily the vertical scroll bar. Depending on
-// whether the scroll is horizontal or vertical, it is either the
-// horizontal or vertical scroll bar. nY is correspondingly either
-// the horizontal or vertical scroll amount.
-
 void Window::ImplHandleScroll( Scrollable* pHScrl, double nX,
                                Scrollable* pVScrl, double nY )
 {

Reply via email to