sw/inc/crsrsh.hxx                    |    8 ++++----
 sw/inc/fesh.hxx                      |    2 +-
 sw/inc/mdiexp.hxx                    |    4 +++-
 sw/inc/view.hxx                      |    7 +++++--
 sw/inc/viewsh.hxx                    |    9 ++++++++-
 sw/source/core/crsr/crsrsh.cxx       |   19 ++++++++++---------
 sw/source/core/frmedt/feshview.cxx   |    4 ++--
 sw/source/core/view/viewsh.cxx       |    4 ++--
 sw/source/ui/dialog/uiregionsw.cxx   |    2 +-
 sw/source/ui/index/swuiidxmrk.cxx    |    2 +-
 sw/source/ui/misc/insfnote.cxx       |    6 +++---
 sw/source/uibase/dochdl/swdtflvr.cxx |    2 +-
 sw/source/uibase/docvw/edtdd.cxx     |    4 ++--
 sw/source/uibase/docvw/edtwin.cxx    |   22 ++++++++++++++--------
 sw/source/uibase/docvw/edtwin3.cxx   |    5 +++--
 sw/source/uibase/inc/edtwin.hxx      |    4 +++-
 sw/source/uibase/inc/wrtsh.hxx       |   20 +++++++++++++-------
 sw/source/uibase/shells/tabsh.cxx    |    2 +-
 sw/source/uibase/shells/textsh1.cxx  |    2 +-
 sw/source/uibase/uiview/viewport.cxx |   29 +++++++++++++++++++++++------
 sw/source/uibase/uno/unotxdoc.cxx    |    2 +-
 sw/source/uibase/wrtsh/move.cxx      |    6 +++---
 sw/source/uibase/wrtsh/select.cxx    |   16 ++++++++--------
 sw/source/uibase/wrtsh/wrtsh3.cxx    |    8 ++++----
 24 files changed, 117 insertions(+), 72 deletions(-)

New commits:
commit 47bf215cc7693bde89143f63b88556c61a68a132
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Wed Dec 18 15:11:38 2024 +0100
Commit:     Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
CommitDate: Tue Jan 21 12:13:16 2025 +0100

    tdf#50743 tdf#37507 Improve scrolling while selecting
    
    If the mouse leaves the document window scrolling of selections
    happens now in smaller steps so the user is able to stop at the
    intended position easier.
    
    Change-Id: Ifd21c92936021f8e2213d34446672e2a8eab568f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178724
    Reviewed-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
    Tested-by: Jenkins
    Tested-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 08aae0878d93..773379e1eb0a 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -168,7 +168,7 @@ public:
 
     SW_DLLPUBLIC void UpdateCursor(
         sal_uInt16 eFlags = SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE,
-        bool bIdleEnd = false );
+        bool bIdleEnd = false, ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault );
 
 private:
 
@@ -422,7 +422,7 @@ public:
      *        the cursor is done in order to get at the properties under the 
mouse pointer.
      */
     SW_DLLPUBLIC int SetCursor(const Point& rPt, bool bOnlyText = false, bool 
bBlock = true,
-                  bool bFieldInfo = false);
+                  bool bFieldInfo = false, ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault);
 
     /*
      * Notification that the visible area was changed. m_aVisArea is reset, 
then
@@ -735,7 +735,7 @@ public:
     // Place only the visible cursor at the given position in the document.
     // Return false if SPoint was corrected by layout.
     // (This is needed for displaying the Drag&Drop/Copy-Cursor.)
-    bool SetVisibleCursor( const Point &rPt );
+    bool SetVisibleCursor( const Point &rPt, ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault );
     inline void UnSetVisibleCursor();
     SW_DLLPUBLIC SwVisibleCursor* GetVisibleCursor() const;
 
@@ -817,7 +817,7 @@ public:
     bool GotoRegion( std::u16string_view rName );
 
     // show the current selection
-    virtual void MakeSelVisible();
+    virtual void MakeSelVisible(ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault);
 
     // set the cursor to a NOT protected/hidden node
     bool FindValidContentNode( bool bOnlyText );
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index 94f5f0d3c09e..c1b1ae7e9881 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -360,7 +360,7 @@ public:
     void SetPageObjsNewPage( std::vector<SwFrameFormat*>& rFillArr );
 
     /// Show current selection (frame / draw object as required).
-    virtual void MakeSelVisible() override;
+    virtual void MakeSelVisible(ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault) override;
 
     /** @return FrameFormat of object that may be under Point.
      Object does not become selected! */
diff --git a/sw/inc/mdiexp.hxx b/sw/inc/mdiexp.hxx
index afe308e1ad89..6d4af73bd80b 100644
--- a/sw/inc/mdiexp.hxx
+++ b/sw/inc/mdiexp.hxx
@@ -22,6 +22,7 @@
 #include "tblenum.hxx"
 #include "swdllapi.h"
 #include <unotools/resmgr.hxx>
+#include "viewsh.hxx"
 
 #include <string_view>
 
@@ -30,7 +31,8 @@ class Size;
 class SwViewShell;
 class SwDocShell;
 
-extern void ScrollMDI(SwViewShell const * pVwSh, const SwRect &, sal_uInt16 
nRangeX, sal_uInt16 nRangeY);
+extern void ScrollMDI(SwViewShell const * pVwSh, const SwRect &, sal_uInt16 
nRangeX, sal_uInt16 nRangeY
+    , ScrollSizeMode eScrollSizeMode = ScrollSizeMode::ScrollSizeDefault);
 extern bool IsScrollMDI(SwViewShell const * pVwSh, const SwRect &);
 extern void SizeNotify(SwViewShell const * pVwSh, const Size &);
 
diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index 3eba3163d333..220c97af2627 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -31,6 +31,7 @@
 #include "swdllapi.h"
 #include "swtypes.hxx"
 #include "shellid.hxx"
+#include "viewsh.hxx"
 
 #include <svx/sdr/overlay/overlayobject.hxx>
 
@@ -302,7 +303,8 @@ class SW_DLLPUBLIC SwView: public SfxViewShell
     SAL_DLLPRIVATE Point         AlignToPixel(const Point& rPt) const;
     SAL_DLLPRIVATE void          CalcPt( Point* pPt,const tools::Rectangle& 
rRect,
                                     sal_uInt16 nRangeX,
-                                    sal_uInt16 nRangeY);
+                                    sal_uInt16 nRangeY,
+                                    ScrollSizeMode eScrollSizeMode);
 
     SAL_DLLPRIVATE bool          GetPageScrollUpOffset(SwTwips& rOff) const;
     SAL_DLLPRIVATE bool          GetPageScrollDownOffset(SwTwips& rOff) const;
@@ -447,7 +449,8 @@ public:
     bool            IsScroll(const tools::Rectangle& rRect) const;
     void            Scroll( const tools::Rectangle& rRect,
                             sal_uInt16 nRangeX = USHRT_MAX,
-                            sal_uInt16 nRangeY = USHRT_MAX);
+                            sal_uInt16 nRangeY = USHRT_MAX,
+                            ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault);
 
     tools::Long            SetVScrollMax(tools::Long lMax);
     tools::Long            SetHScrollMax(tools::Long lMax);
diff --git a/sw/inc/viewsh.hxx b/sw/inc/viewsh.hxx
index b75ff5009d83..7b2565f18703 100644
--- a/sw/inc/viewsh.hxx
+++ b/sw/inc/viewsh.hxx
@@ -84,6 +84,13 @@ enum class LockPaintReason
     ExampleFrame
 };
 
+enum class ScrollSizeMode
+{
+    ScrollSizeDefault, //usually 30% of the visible area
+    ScrollSizeMouseSelection, //make target rectangle visible
+    ScrollSizeTimer, // increase of timer based scrolling
+    ScrollSizeTimer2 // more increase of timer based scrolling
+};
 namespace vcl
 {
     typedef OutputDevice RenderContext;
@@ -286,7 +293,7 @@ public:
     void setLOKVisibleArea(const tools::Rectangle& rArea) { maLOKVisibleArea = 
rArea; }
 
     // If necessary scroll until passed Rect is situated in visible sector.
-    void MakeVisible( const SwRect & );
+    void MakeVisible( const SwRect &, ScrollSizeMode eScrollSizeMode = 
ScrollSizeMode::ScrollSizeDefault );
 
     // At nearest occasion pass new document size to UI.
     void SizeChgNotify();
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 12ded9650e55..3ef4fd73b492 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1056,7 +1056,8 @@ bool SwCursorShell::IsInHeaderFooter( bool* pbInHeader ) 
const
     return nullptr != pFrame;
 }
 
-int SwCursorShell::SetCursor(const Point& rLPt, bool bOnlyText, bool bBlock, 
bool bFieldInfo)
+int SwCursorShell::SetCursor(const Point& rLPt, bool bOnlyText, bool bBlock,
+    bool bFieldInfo, ScrollSizeMode eScrollSizeMode)
 {
     CurrShell aCurr( this );
 
@@ -1161,7 +1162,7 @@ int SwCursorShell::SetCursor(const Point& rLPt, bool 
bOnlyText, bool bBlock, boo
 
     if( !pCursor->IsSelOvr( SwCursorSelOverFlags::ChangePos ) )
     {
-        UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE );
+        UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE, 
false, eScrollSizeMode );
         bRet &= ~CRSR_POSOLD;
     }
     else if( bOnlyText && !m_pCurrentCursor->HasMark() )
@@ -1943,7 +1944,7 @@ class SwNotifyAccAboutInvalidTextSelections
 }
 #endif
 
-void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd )
+void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool bIdleEnd, 
ScrollSizeMode eScrollSizeMode )
 {
     Point nOldPos = m_pCurrentCursor->GetPtPos();
     CurrShell aCurr( this );
@@ -2387,7 +2388,7 @@ void SwCursorShell::UpdateCursor( sal_uInt16 eFlags, bool 
bIdleEnd )
             // again, thus save and reset the flag here
             bool bSav = m_bSVCursorVis;
             m_bSVCursorVis = false;
-            MakeSelVisible();
+            MakeSelVisible(eScrollSizeMode);
             m_bSVCursorVis = bSav;
         }
 
@@ -3093,7 +3094,7 @@ bool SwCursorShell::ExtendSelection( bool bEnd, sal_Int32 
nCount )
     @param rPt The position to move the visible cursor to.
     @return <false> if SPoint was corrected by the layout.
 */
-bool SwCursorShell::SetVisibleCursor( const Point &rPt )
+bool SwCursorShell::SetVisibleCursor( const Point &rPt, ScrollSizeMode 
eScrollSizeMode )
 {
     CurrShell aCurr( this );
     Point aPt( rPt );
@@ -3132,7 +3133,7 @@ bool SwCursorShell::SetVisibleCursor( const Point &rPt )
     m_pVisibleCursor->Hide(); // always hide visible cursor
     if( IsScrollMDI( this, m_aCharRect ))
     {
-        MakeVisible( m_aCharRect );
+        MakeVisible( m_aCharRect, eScrollSizeMode );
         m_pCurrentCursor->Show(nullptr);
     }
 
@@ -3520,7 +3521,7 @@ size_t SwCursorShell::UpdateTableSelBoxes()
 }
 
 /// show the current selected "object"
-void SwCursorShell::MakeSelVisible()
+void SwCursorShell::MakeSelVisible(ScrollSizeMode eScrollSizeMode)
 {
     OSL_ENSURE( m_bHasFocus, "no focus but cursor should be made visible?" );
     if( m_aCursorHeight.Y() < m_aCharRect.Height() && m_aCharRect.Height() > 
VisArea().Height() )
@@ -3544,13 +3545,13 @@ void SwCursorShell::MakeSelVisible()
     else
     {
         if( m_aCharRect.HasArea() )
-            MakeVisible( m_aCharRect );
+            MakeVisible( m_aCharRect, eScrollSizeMode );
         else
         {
             SwRect aTmp( m_aCharRect );
             aTmp.AddHeight(1 );
             aTmp.AddWidth(1 );
-            MakeVisible( aTmp );
+            MakeVisible( aTmp, eScrollSizeMode );
         }
     }
 }
diff --git a/sw/source/core/frmedt/feshview.cxx 
b/sw/source/core/frmedt/feshview.cxx
index 4fc5286e0101..1e2d117e759c 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -2669,7 +2669,7 @@ std::vector<SwFrameFormat const*> 
SwFEShell::GetFlyFrameFormats(
 }
 
 // show the current selected object
-void SwFEShell::MakeSelVisible()
+void SwFEShell::MakeSelVisible(ScrollSizeMode eScrollSizeMode)
 {
     if ( Imp()->HasDrawView() &&
          Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )
@@ -2678,7 +2678,7 @@ void SwFEShell::MakeSelVisible()
         MakeVisible( SwRect(Imp()->GetDrawView()->GetAllMarkedRect()) );
     }
     else
-        SwCursorShell::MakeSelVisible();
+        SwCursorShell::MakeSelVisible(eScrollSizeMode);
 }
 
 // how is the selected object protected?
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 9e3820953de6..e8db55ee359c 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -682,7 +682,7 @@ const SwRect& SwViewShell::VisArea() const
     return comphelper::LibreOfficeKit::isActive()? 
GetLayout()->getFrameArea(): maVisArea;
 }
 
-void SwViewShell::MakeVisible( const SwRect &rRect )
+void SwViewShell::MakeVisible( const SwRect &rRect, ScrollSizeMode 
eScrollSizeMode )
 {
     if ( !(!VisArea().Contains( rRect ) || IsScrollMDI( this, rRect ) || 
GetCareDialog(*this)) )
         return;
@@ -698,7 +698,7 @@ void SwViewShell::MakeVisible( const SwRect &rRect )
         do{
             nOldH = pRoot->getFrameArea().Height();
             SwViewShell::StartAction();
-            ScrollMDI( this, rRect, USHRT_MAX, USHRT_MAX );
+            ScrollMDI( this, rRect, USHRT_MAX, USHRT_MAX, eScrollSizeMode );
             SwViewShell::EndAction(); // DO NOT call virtual here!
         } while( nOldH != pRoot->getFrameArea().Height() && nLoopCnt-- );
     }
diff --git a/sw/source/ui/dialog/uiregionsw.cxx 
b/sw/source/ui/dialog/uiregionsw.cxx
index 16c6cda95b58..92dccb18e1da 100644
--- a/sw/source/ui/dialog/uiregionsw.cxx
+++ b/sw/source/ui/dialog/uiregionsw.cxx
@@ -764,7 +764,7 @@ IMPL_LINK_NOARG(SwEditRegionDlg, OkHdl, weld::Button&, void)
 
     m_rSh.StartAllAction();
     m_rSh.StartUndo();
-    m_rSh.ResetSelect( nullptr,false );
+    m_rSh.ResetSelect( nullptr,false, ScrollSizeMode::ScrollSizeDefault );
 
     std::unique_ptr<weld::TreeIter> xIter(m_xTree->make_iterator());
     if (m_xTree->get_iter_first(*xIter))
diff --git a/sw/source/ui/index/swuiidxmrk.cxx 
b/sw/source/ui/index/swuiidxmrk.cxx
index 2bc41b0889a4..58a0f1f65621 100644
--- a/sw/source/ui/index/swuiidxmrk.cxx
+++ b/sw/source/ui/index/swuiidxmrk.cxx
@@ -453,7 +453,7 @@ void SwIndexMarkPane::Apply()
 {
     InsertUpdate();
     if(m_bSelected)
-        m_pSh->ResetSelect(nullptr, false);
+        m_pSh->ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
 }
 
 // apply changes
diff --git a/sw/source/ui/misc/insfnote.cxx b/sw/source/ui/misc/insfnote.cxx
index dacf8308fe72..a43bd61eacd8 100644
--- a/sw/source/ui/misc/insfnote.cxx
+++ b/sw/source/ui/misc/insfnote.cxx
@@ -58,7 +58,7 @@ void SwInsFootNoteDlg::Apply()
                                m_eCharSet, RES_CHRATR_FONT );
             aSet.Put( aFont );
             m_rSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND );
-            m_rSh.ResetSelect(nullptr, false);
+            m_rSh.ResetSelect(nullptr, false, 
ScrollSizeMode::ScrollSizeDefault);
             m_rSh.Left(SwCursorSkipMode::Chars, false, 1, false );
         }
         m_rSh.EndUndo( SwUndoId::END );
@@ -138,7 +138,7 @@ IMPL_LINK( SwInsFootNoteDlg, NextPrevHdl, weld::Button&, 
rBtn, void )
     Apply();
 
     // go to the next foot/endnote here
-    m_rSh.ResetSelect(nullptr, false);
+    m_rSh.ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
     if (&rBtn == m_xNextBT.get())
         m_rSh.GotoNextFootnoteAnchor();
     else
@@ -188,7 +188,7 @@ void SwInsFootNoteDlg::ImplDestroy()
     SwViewShell::SetCareDialog(nullptr);
 
     if (m_bEdit)
-        m_rSh.ResetSelect(nullptr, false);
+        m_rSh.ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
 }
 
 SwInsFootNoteDlg::~SwInsFootNoteDlg()
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx 
b/sw/source/uibase/dochdl/swdtflvr.cxx
index 5f775e7a3d96..11847f90b53d 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -3877,7 +3877,7 @@ bool SwTransferable::PrivatePaste(SwWrtShell& rShell, 
SwPasteContext* pContext,
     }
     if ( nSelection & SelectionType::DrawObject) //unselect hovering graphics
     {
-        rShell.ResetSelect(nullptr,false);
+        rShell.ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
     }
 
     bool bInWrd = false, bEndWrd = false, bSttWrd = false,
diff --git a/sw/source/uibase/docvw/edtdd.cxx b/sw/source/uibase/docvw/edtdd.cxx
index 72e50a65599e..89f93144919d 100644
--- a/sw/source/uibase/docvw/edtdd.cxx
+++ b/sw/source/uibase/docvw/edtdd.cxx
@@ -371,7 +371,7 @@ sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt 
)
             if(aPixPt.Y() < aWin.Top()) aPixPt.AdjustY( -nMargin );
             Point aDocPt(PixelToLogic(aPixPt));
             SwRect rect(aDocPt,Size(1,1));
-            rSh.MakeVisible(rect);
+            rSh.MakeVisible(rect, ScrollSizeMode::ScrollSizeTimer2);
         }
     }
 
@@ -461,7 +461,7 @@ sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt 
)
             CleanupDropUserMarker();
             SwContentAtPos aCont( IsAttrAtPos::ContentCheck );
             if(rSh.GetContentAtPos(aDocPt, aCont))
-                rSh.SwCursorShell::SetVisibleCursor( aDocPt );
+                rSh.SwCursorShell::SetVisibleCursor( aDocPt, 
ScrollSizeMode::ScrollSizeMouseSelection );
         }
         else
         {
diff --git a/sw/source/uibase/docvw/edtwin.cxx 
b/sw/source/uibase/docvw/edtwin.cxx
index f8ce91be0426..efaf125578e9 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -682,7 +682,7 @@ IMPL_LINK_NOARG(SwEditWin, TimerHandler, Timer *, void)
             rSh.SelectTableRowCol( *m_xRowColumnSelectionStart, &aPos, 
m_bIsRowDrag );
         }
         else
-            rSh.CallSetCursor( &aModPt, false );
+            rSh.CallSetCursor( &aModPt, false, m_eScrollSizeMode );
 
         // It can be that a "jump" over a table cannot be accomplished like
         // that. So we jump over the table by Up/Down here.
@@ -706,15 +706,20 @@ void SwEditWin::JustifyAreaTimer()
 {
     const tools::Rectangle &rVisArea = GetView().GetVisArea();
 #ifdef UNX
-    const tools::Long coMinLen = 100;
+    const tools::Long coMinLen = 40;
 #else
-    const tools::Long coMinLen = 50;
+    const tools::Long coMinLen = 20;
 #endif
     tools::Long const nTimeout = 800,
          nDiff = std::max(
          std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - 
m_aMovePos.Y() ),
          std::max( m_aMovePos.X() - rVisArea.Right(),  rVisArea.Left() - 
m_aMovePos.X()));
-    m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) );
+    m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff) );
+    m_eScrollSizeMode = m_aTimer.GetTimeout() < 100 ?
+        ScrollSizeMode::ScrollSizeTimer2 :
+        m_aTimer.GetTimeout() < 400 ?
+            ScrollSizeMode::ScrollSizeTimer :
+            ScrollSizeMode::ScrollSizeMouseSelection;
 }
 
 void SwEditWin::LeaveArea(const Point &rPos)
@@ -3970,7 +3975,7 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
 
                 if ( !bOverSelect || rSh.IsInSelect() )
                 {
-                    MoveCursor( rSh, aDocPos, bOnlyText, bLockView );
+                    MoveCursor( rSh, aDocPos, bOnlyText, bLockView);
                     bCallBase = false;
                 }
                 if (!bOverURLGrf && !bExecDrawTextLink && !bOnlyText)
@@ -4569,8 +4574,8 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
                           rSh.IsAddMode() ) )
                     {
                         rSh.Drag( &aDocPt, false );
-
-                        g_bValidCursorPos = !(CRSR_POSCHG & 
rSh.CallSetCursor(&aDocPt, false));
+                        g_bValidCursorPos = !(CRSR_POSCHG & 
rSh.CallSetCursor(&aDocPt, false,
+                            ScrollSizeMode::ScrollSizeMouseSelection));
                         EnterArea();
                     }
                 }
@@ -5498,6 +5503,7 @@ SwEditWin::SwEditWin(vcl::Window *pParent, SwView 
&rMyView):
     m_aTimer("SwEditWin"),
     m_aKeyInputFlushTimer("SwEditWin m_aKeyInputFlushTimer"),
     m_eBufferLanguage(LANGUAGE_DONTKNOW),
+    m_eScrollSizeMode(ScrollSizeMode::ScrollSizeMouseSelection),
     m_aTemplateTimer("SwEditWin m_aTemplateTimer"),
     m_pUserMarkerObj( nullptr ),
 
@@ -6312,7 +6318,7 @@ void SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const 
Point& rMousePos )
         // the query against the content form doesn't work!!!
         SwMvContext aMvContext( &rSh );
         if (rSh.HasSelection())
-            rSh.ResetSelect(&aDocPos, false);
+            rSh.ResetSelect(&aDocPos, false, 
ScrollSizeMode::ScrollSizeDefault);
         rSh.SwCursorShell::SetCursor(aDocPos, false, /*Block=*/false, 
/*FieldInfo=*/true);
     }
     if( !bOverURLGrf )
diff --git a/sw/source/uibase/docvw/edtwin3.cxx 
b/sw/source/uibase/docvw/edtwin3.cxx
index 4a60637c9624..432e58fc2d5e 100644
--- a/sw/source/uibase/docvw/edtwin3.cxx
+++ b/sw/source/uibase/docvw/edtwin3.cxx
@@ -33,12 +33,13 @@
 
 // Core-Notify
 void ScrollMDI( SwViewShell const * pVwSh, const SwRect &rRect,
-                sal_uInt16 nRangeX, sal_uInt16 nRangeY)
+                sal_uInt16 nRangeX, sal_uInt16 nRangeY,
+                ScrollSizeMode eScrollSizeMode)
 {
     SfxViewShell *pSfxViewShell = pVwSh->GetSfxViewShell();
 
     if (SwView* pSwView = dynamic_cast<SwView *>(pSfxViewShell))
-        pSwView->Scroll(rRect.SVRect(), nRangeX, nRangeY);
+        pSwView->Scroll(rRect.SVRect(), nRangeX, nRangeY, eScrollSizeMode);
 }
 
 // Docmdi - movable
diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx
index 53e7ddf16568..bb87a61a39ca 100644
--- a/sw/source/uibase/inc/edtwin.hxx
+++ b/sw/source/uibase/inc/edtwin.hxx
@@ -28,6 +28,7 @@
 #include <vcl/transfer.hxx>
 #include <swevent.hxx>
 #include <swtypes.hxx>
+#include <viewsh.hxx>
 
 class   SwWrtShell;
 class   SwView;
@@ -81,6 +82,7 @@ class SAL_DLLPUBLIC_RTTI SwEditWin final : public 
vcl::DocWindow,
     LanguageType    m_eBufferLanguage;
     Point           m_aStartPos;
     Point           m_aMovePos;
+    ScrollSizeMode  m_eScrollSizeMode;
     Point           m_aRszMvHdlPt;
     Timer           m_aTemplateTimer;
 
@@ -171,7 +173,7 @@ class SAL_DLLPUBLIC_RTTI SwEditWin final : public 
vcl::DocWindow,
     DECL_LINK( TemplateTimerHdl, Timer *, void );
 
     void            MoveCursor( SwWrtShell &rSh, const Point& rDocPos,
-                                const bool bOnlyText, bool bLockView );
+                                const bool bOnlyText, bool bLockView);
 
     virtual void    DataChanged( const DataChangedEvent& ) override;
     virtual void    PrePaint(vcl::RenderContext& rRenderContext) override;
diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx
index bc9763c0b1e0..21a59b8c039b 100644
--- a/sw/source/uibase/inc/wrtsh.hxx
+++ b/sw/source/uibase/inc/wrtsh.hxx
@@ -108,7 +108,7 @@ private:
     using SwEditShell::AutoCorrect;
     using SwCursorShell::GotoMark;
 
-    typedef tools::Long (SwWrtShell::*SELECTFUNC)(const Point *, bool bProp );
+    typedef tools::Long (SwWrtShell::*SELECTFUNC)(const Point *, bool bProp, 
ScrollSizeMode eScrollSizeMode );
     typedef void (SwWrtShell::*SELECTFUNC2)(const Point *, bool bProp );
 
     SELECTFUNC2 m_fnDrag      = &SwWrtShell::BeginDrag;
@@ -120,16 +120,20 @@ public:
     using SwCursorShell::GotoFootnoteAnchor;
     using SwEditShell::Insert;
 
-    tools::Long CallSetCursor(const Point* pPt, bool bProp) { return 
(this->*m_fnSetCursor)(pPt, bProp); }
+    tools::Long CallSetCursor(const Point* pPt, bool bProp,
+        ScrollSizeMode eScrollSizeMode = ScrollSizeMode::ScrollSizeDefault)
+        { return (this->*m_fnSetCursor)(pPt, bProp, eScrollSizeMode); }
     void Drag         (const Point* pPt, bool bProp) { (this->*m_fnDrag)(pPt, 
bProp); }
     void EndDrag      (const Point* pPt, bool bProp) { 
(this->*m_fnEndDrag)(pPt, bProp); }
-    tools::Long KillSelection(const Point* pPt, bool bProp) { return 
(this->*m_fnKillSel)(pPt, bProp); }
+    tools::Long KillSelection(const Point* pPt, bool bProp,
+        ScrollSizeMode eScrollSizeMode = ScrollSizeMode::ScrollSizeDefault)
+        { return (this->*m_fnKillSel)(pPt, bProp, eScrollSizeMode ); }
 
     bool IsSplitVerticalByDefault() const;
     void SetSplitVerticalByDefault(bool value);
 
     // reset all selections
-    SW_DLLPUBLIC tools::Long ResetSelect( const Point *, bool );
+    SW_DLLPUBLIC tools::Long ResetSelect( const Point *, bool, ScrollSizeMode 
);
 
     // resets the cursorstack after movement with PageUp/-Down if a stack is 
built up
     inline void ResetCursorStack();
@@ -614,9 +618,11 @@ private:
     void  ResetCursorStack_();
 
     using SwCursorShell::SetCursor;
-    tools::Long  SetCursor(const Point *, bool bProp=false );
+    tools::Long  SetCursor(const Point *, bool bProp=false,
+        ScrollSizeMode eScrollSizeMode = ScrollSizeMode::ScrollSizeDefault );
 
-    tools::Long  SetCursorKillSel(const Point *, bool bProp );
+    tools::Long  SetCursorKillSel(const Point *, bool bProp,
+        ScrollSizeMode eScrollSizeMode = ScrollSizeMode::ScrollSizeDefault );
 
     void  BeginDrag(const Point *, bool bProp );
     void  DefaultDrag(const Point *, bool bProp );
@@ -632,7 +638,7 @@ private:
 
     void  SttLeaveSelect();
     void  AddLeaveSelect();
-    tools::Long  Ignore(const Point *, bool bProp );
+    tools::Long  Ignore(const Point *, bool bProp, ScrollSizeMode 
eScrollSizeMode = ScrollSizeMode::ScrollSizeDefault );
 
     void  LeaveExtSel() { m_bSelWrd = m_bSelLn = false;}
 
diff --git a/sw/source/uibase/shells/tabsh.cxx 
b/sw/source/uibase/shells/tabsh.cxx
index e75bb001df08..3664e17c50de 100644
--- a/sw/source/uibase/shells/tabsh.cxx
+++ b/sw/source/uibase/shells/tabsh.cxx
@@ -858,7 +858,7 @@ void SwTableShell::Execute(SfxRequest &rReq)
             break;
         case FN_TABLE_SET_READ_ONLY_CELLS:
             rSh.ProtectCells();
-            rSh.ResetSelect( nullptr, false );
+            rSh.ResetSelect( nullptr, false, ScrollSizeMode::ScrollSizeDefault 
);
             bCallDone = true;
             break;
         case FN_TABLE_UNSET_READ_ONLY_CELLS:
diff --git a/sw/source/uibase/shells/textsh1.cxx 
b/sw/source/uibase/shells/textsh1.cxx
index 0c357d1d77d0..6ec961fcac00 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -1144,7 +1144,7 @@ void SwTextShell::Execute(SfxRequest &rReq)
                 SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONT> aSet( 
rWrtSh.GetAttrPool() );
                 rWrtSh.GetCurAttr( aSet );
                 rWrtSh.SetAttrSet( aSet, SetAttrMode::DONTEXPAND );
-                rWrtSh.ResetSelect(nullptr, false);
+                rWrtSh.ResetSelect(nullptr, false, 
ScrollSizeMode::ScrollSizeDefault);
                 rWrtSh.EndSelect();
                 rWrtSh.GotoFootnoteText();
             }
diff --git a/sw/source/uibase/uiview/viewport.cxx 
b/sw/source/uibase/uiview/viewport.cxx
index f511f4a8e354..4fab16ff7755 100644
--- a/sw/source/uibase/uiview/viewport.cxx
+++ b/sw/source/uibase/uiview/viewport.cxx
@@ -339,14 +339,29 @@ void SwView::CheckVisArea()
 //                              within the new visible area.
 //  sal_uInt16 nRange           optional accurate indication of the
 //                              range by which to scroll if necessary.
+//  eScrollSizeMode             mouse selection should only bring the selected 
part
+//                              into the visible area, timer call needs 
increased size
 
-void SwView::CalcPt( Point *pPt, const tools::Rectangle &rRect,
-                     sal_uInt16 nRangeX, sal_uInt16 nRangeY)
+void SwView::CalcPt( Point *pPt, const tools::Rectangle &rRect, sal_uInt16 
nRangeX,
+                    sal_uInt16 nRangeY, ScrollSizeMode eScrollSizeMode)
 {
 
     const SwTwips lMin = IsDocumentBorder() ? DOCUMENTBORDER : 0;
 
-    tools::Long nYScroll = GetYScroll();
+    const tools::Long nDefaultYScroll = GetYScroll();
+    tools::Long nYScroll;
+    if (eScrollSizeMode != ScrollSizeMode::ScrollSizeDefault)
+    {
+        nYScroll = m_aVisArea.Top() > rRect.Top() ?
+            m_aVisArea.Top() - rRect.Top() :
+            rRect.Bottom() - m_aVisArea.Bottom();
+        if (eScrollSizeMode == ScrollSizeMode::ScrollSizeTimer)
+             nYScroll = std::min(nDefaultYScroll, nYScroll * 5);
+        else if (eScrollSizeMode == ScrollSizeMode::ScrollSizeTimer2)
+             nYScroll = 2 * nDefaultYScroll;
+    }
+    else
+        nYScroll = nDefaultYScroll;
     tools::Long nDesHeight = rRect.GetHeight();
     tools::Long nCurHeight = m_aVisArea.GetHeight();
     nYScroll = std::min(nYScroll, nCurHeight - nDesHeight); // If it is 
scarce, then scroll not too much.
@@ -391,7 +406,8 @@ bool SwView::IsScroll( const tools::Rectangle &rRect ) const
     return m_bCenterCursor || m_bTopCursor || !m_aVisArea.Contains(rRect);
 }
 
-void SwView::Scroll( const tools::Rectangle &rRect, sal_uInt16 nRangeX, 
sal_uInt16 nRangeY )
+void SwView::Scroll( const tools::Rectangle &rRect, sal_uInt16 nRangeX, 
sal_uInt16 nRangeY
+    , ScrollSizeMode eScrollSizeMode )
 {
     if ( m_aVisArea.IsEmpty() )
         return;
@@ -463,7 +479,8 @@ void SwView::Scroll( const tools::Rectangle &rRect, 
sal_uInt16 nRangeX, sal_uInt
 
         CalcPt( &aPt, tools::Rectangle( rRect.TopLeft(), aSize ),
                 static_cast< sal_uInt16 >((aVisSize.Width() - aSize.Width()) / 
2),
-                static_cast< sal_uInt16 >((aVisSize.Height()- aSize.Height())/ 
2) );
+                static_cast< sal_uInt16 >((aVisSize.Height()- aSize.Height())/ 
2),
+                eScrollSizeMode );
 
         if( m_bTopCursor )
         {
@@ -480,7 +497,7 @@ void SwView::Scroll( const tools::Rectangle &rRect, 
sal_uInt16 nRangeX, sal_uInt
     if( !m_bCenterCursor )
     {
         Point aPt( m_aVisArea.TopLeft() );
-        CalcPt( &aPt, rRect, nRangeX, nRangeY );
+        CalcPt( &aPt, rRect, nRangeX, nRangeY, eScrollSizeMode );
 
         if( m_bTopCursor )
         {
diff --git a/sw/source/uibase/uno/unotxdoc.cxx 
b/sw/source/uibase/uno/unotxdoc.cxx
index 7052d22ca1c1..000564fbbc76 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -4072,7 +4072,7 @@ void SwXTextDocument::resetSelection()
     SolarMutexGuard aGuard;
 
     SwWrtShell* pWrtShell = m_pDocShell->GetWrtShell();
-    pWrtShell->ResetSelect(nullptr, false);
+    pWrtShell->ResetSelect(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
 }
 
 void SAL_CALL SwXTextDocument::paintTile( const ::css::uno::Any& Parent, 
::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, 
::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight )
diff --git a/sw/source/uibase/wrtsh/move.cxx b/sw/source/uibase/wrtsh/move.cxx
index 784a3992d584..a2c50dae8582 100644
--- a/sw/source/uibase/wrtsh/move.cxx
+++ b/sw/source/uibase/wrtsh/move.cxx
@@ -84,7 +84,7 @@ void SwWrtShell::MoveCursor( bool bWithSelect )
     else
     {
         EndSelect();
-        (this->*m_fnKillSel)( nullptr, false );
+        (this->*m_fnKillSel)( nullptr, false, 
ScrollSizeMode::ScrollSizeDefault );
     }
 }
 
@@ -498,7 +498,7 @@ bool SwWrtShell::PushCursor(SwTwips lOffset, bool bSelect)
             CallChgLnk();
         }
 
-        (this->*m_fnSetCursor)( &m_aDest, true );
+        (this->*m_fnSetCursor)( &m_aDest, true, 
ScrollSizeMode::ScrollSizeDefault );
 
         bDiff = aOldRect != GetCharRect();
 
@@ -539,7 +539,7 @@ bool SwWrtShell::PopCursor(bool bUpdate, bool bSelect)
             else
                 EndSelect();
 
-            (this->*m_fnSetCursor)(&m_pCursorStack->aDocPos, 
!m_pCursorStack->bIsFrameSel);
+            (this->*m_fnSetCursor)(&m_pCursorStack->aDocPos, 
!m_pCursorStack->bIsFrameSel, ScrollSizeMode::ScrollSizeDefault);
             if( m_pCursorStack->bIsFrameSel && 
IsObjSelectable(m_pCursorStack->aDocPos))
             {
                 HideCursor();
diff --git a/sw/source/uibase/wrtsh/select.cxx 
b/sw/source/uibase/wrtsh/select.cxx
index 7d15d2cb4d68..fc502783003b 100644
--- a/sw/source/uibase/wrtsh/select.cxx
+++ b/sw/source/uibase/wrtsh/select.cxx
@@ -318,7 +318,7 @@ void SwWrtShell::PopMode()
 // eponymous methods in the CursorShell, the second removes
 // all selections at first.
 
-tools::Long SwWrtShell::SetCursor(const Point *pPt, bool bTextOnly)
+tools::Long SwWrtShell::SetCursor(const Point *pPt, bool bTextOnly, 
ScrollSizeMode eScrollSizeMode)
 {
         // Remove a possibly present selection at the position
         // of the mouseclick
@@ -327,14 +327,14 @@ tools::Long SwWrtShell::SetCursor(const Point *pPt, bool 
bTextOnly)
         ClearMark();
     }
 
-    return SwCursorShell::SetCursor(*pPt, bTextOnly);
+    return SwCursorShell::SetCursor(*pPt, bTextOnly, true, false, 
eScrollSizeMode );
 }
 
-tools::Long SwWrtShell::SetCursorKillSel(const Point *pPt, bool bTextOnly )
+tools::Long SwWrtShell::SetCursorKillSel(const Point *pPt, bool bTextOnly, 
ScrollSizeMode eScrollSizeMode )
 {
     SwActContext aActContext(this);
-    ResetSelect(pPt,false);
-    return SwCursorShell::SetCursor(*pPt, bTextOnly);
+    ResetSelect(pPt, false, ScrollSizeMode::ScrollSizeDefault);
+    return SwCursorShell::SetCursor(*pPt, bTextOnly, true, false, 
eScrollSizeMode);
 }
 
 void SwWrtShell::UnSelectFrame()
@@ -347,7 +347,7 @@ void SwWrtShell::UnSelectFrame()
 
 // Remove of all selections
 
-tools::Long SwWrtShell::ResetSelect(const Point *,bool)
+tools::Long SwWrtShell::ResetSelect(const Point *, bool, ScrollSizeMode)
 {
     if(IsSelFrameMode())
     {
@@ -393,7 +393,8 @@ void SwWrtShell::SetSplitVerticalByDefault(bool value)
 
 // Do nothing
 
-tools::Long SwWrtShell::Ignore(const Point *, bool ) {
+tools::Long SwWrtShell::Ignore(const Point *, bool, ScrollSizeMode )
+{
     return 1;
 }
 
@@ -674,7 +675,6 @@ void SwWrtShell::EnterAddMode()
     if(IsTableMode()) return;
     if(m_bBlockMode)
         LeaveBlockMode();
-    m_fnKillSel = &SwWrtShell::Ignore;
     m_fnSetCursor = &SwWrtShell::SetCursor;
     m_bAddMode = true;
     m_bBlockMode = false;
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx 
b/sw/source/uibase/wrtsh/wrtsh3.cxx
index 36c12ebee17c..2a83ebaeb48f 100644
--- a/sw/source/uibase/wrtsh/wrtsh3.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -49,7 +49,7 @@ using namespace ::com::sun::star;
 bool SwWrtShell::MoveBookMark( BookMarkMove eFuncId, const 
::sw::mark::MarkBase* const pMark)
 {
     addCurrentPosition();
-    (this->*m_fnKillSel)( nullptr, false );
+    (this->*m_fnKillSel)( nullptr, false, ScrollSizeMode::ScrollSizeDefault );
 
     bool bRet = true;
     switch(eFuncId)
@@ -75,7 +75,7 @@ bool SwWrtShell::MoveBookMark( BookMarkMove eFuncId, const 
::sw::mark::MarkBase*
 
 bool SwWrtShell::GotoField( const SwFormatField& rField )
 {
-    (this->*m_fnKillSel)( nullptr, false );
+    (this->*m_fnKillSel)( nullptr, false, ScrollSizeMode::ScrollSizeDefault );
 
     bool bRet = SwCursorShell::GotoFormatField( rField );
     if( bRet && IsSelFrameMode() )
@@ -122,7 +122,7 @@ bool SwWrtShell::GotoContentControl(const 
SwFormatContentControl& rContentContro
         return true;
     }
 
-    (this->*m_fnKillSel)(nullptr, false);
+    (this->*m_fnKillSel)(nullptr, false, ScrollSizeMode::ScrollSizeDefault);
 
     bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl);
 
@@ -223,7 +223,7 @@ bool SwWrtShell::GotoContentControl(const 
SwFormatContentControl& rContentContro
 
 bool SwWrtShell::GotoFieldmark(::sw::mark::Fieldmark const * const pMark)
 {
-    (this->*m_fnKillSel)( nullptr, false );
+    (this->*m_fnKillSel)( nullptr, false, ScrollSizeMode::ScrollSizeDefault );
     bool bRet = SwCursorShell::GotoFieldmark(pMark);
     if( bRet && IsSelFrameMode() )
     {

Reply via email to