Skip to content

Commit ecc84df

Browse files
committed
Warm scrolling above and below.
1 parent 04efcec commit ecc84df

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

Src/Common/SimpleRootSite/SimpleRootSite.cs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ public void OnInputLanguageChanged(IKeyboardDefinition previousKeyboard, IKeyboa
175175
/// as on Mono Setting AutoScrollPosition causes a redraw even when AllowPainting == false
176176
/// </summary>
177177
private Point? cachedAutoScrollPosition = null;
178+
private bool m_fWarmingScrollViewport;
179+
private bool m_fDeferredScrollWarmupPending = true;
180+
private bool m_fDeferredScrollWarmupQueued;
181+
private int m_lastScrollWarmDirection;
182+
private int m_scrollWarmRangeTop = int.MinValue;
183+
private int m_scrollWarmRangeBottom = int.MinValue;
178184

179185
/// <summary>Used to draw the rootbox</summary>
180186
private IVwDrawRootBuffered m_vdrb;
@@ -1620,6 +1626,7 @@ public virtual Point ScrollPosition
16201626
set
16211627
{
16221628
CheckDisposed();
1629+
int previousViewportTop = -AutoScrollPosition.Y;
16231630
Point newPos = value;
16241631
if (this.AutoScroll)
16251632
{
@@ -1637,7 +1644,140 @@ public virtual Point ScrollPosition
16371644
AutoScrollPosition = newPos;
16381645
else
16391646
cachedAutoScrollPosition = newPos;
1647+
1648+
int scrollDelta = newPos.Y - previousViewportTop;
1649+
if (scrollDelta != 0)
1650+
m_lastScrollWarmDirection = Math.Sign(scrollDelta);
1651+
1652+
WarmScrollViewportIfNeeded();
1653+
}
1654+
}
1655+
1656+
protected virtual int ScrollWarmupMargin
1657+
{
1658+
get
1659+
{
1660+
return Math.Max(1, ClientRectangle.Height / 2);
1661+
}
1662+
}
1663+
1664+
protected virtual void WarmScrollViewportIfNeeded()
1665+
{
1666+
WarmScrollViewportIfNeeded(false);
1667+
}
1668+
1669+
private void WarmScrollViewportIfNeeded(bool preferSymmetric)
1670+
{
1671+
if (m_fWarmingScrollViewport || m_fInPaint || m_fInLayout || m_rootb == null ||
1672+
m_dxdLayoutWidth <= 0 || !AllowPainting || ClientRectangle.Height <= 0)
1673+
{
1674+
return;
1675+
}
1676+
1677+
int viewportTop = -ScrollPosition.Y;
1678+
int viewportBottom = viewportTop + ClientRectangle.Height;
1679+
GetScrollWarmupMargins(preferSymmetric, out int warmMarginTop, out int warmMarginBottom);
1680+
if (viewportTop >= m_scrollWarmRangeTop && viewportBottom <= m_scrollWarmRangeBottom)
1681+
{
1682+
m_fDeferredScrollWarmupPending = false;
1683+
return;
1684+
}
1685+
1686+
using (new HoldGraphics(this))
1687+
{
1688+
m_fWarmingScrollViewport = true;
1689+
try
1690+
{
1691+
Rectangle rcSrcRoot;
1692+
Rectangle rcDstRoot;
1693+
GetCoordRects(out rcSrcRoot, out rcDstRoot);
1694+
1695+
if (PrepareToDrawForScrollWarmup(rcSrcRoot, rcDstRoot) == VwPrepDrawResult.kxpdrInvalidate)
1696+
return;
1697+
1698+
if (warmMarginTop > 0)
1699+
{
1700+
if (PrepareToDrawForScrollWarmup(rcSrcRoot, OffsetRootRect(rcDstRoot, -warmMarginTop)) == VwPrepDrawResult.kxpdrInvalidate)
1701+
return;
1702+
}
1703+
1704+
if (warmMarginBottom > 0)
1705+
{
1706+
if (PrepareToDrawForScrollWarmup(rcSrcRoot, OffsetRootRect(rcDstRoot, warmMarginBottom)) == VwPrepDrawResult.kxpdrInvalidate)
1707+
return;
1708+
}
1709+
}
1710+
finally
1711+
{
1712+
m_fWarmingScrollViewport = false;
1713+
}
16401714
}
1715+
1716+
viewportTop = -ScrollPosition.Y;
1717+
viewportBottom = viewportTop + ClientRectangle.Height;
1718+
m_scrollWarmRangeTop = viewportTop - warmMarginTop;
1719+
m_scrollWarmRangeBottom = viewportBottom + warmMarginBottom;
1720+
m_fDeferredScrollWarmupPending = false;
1721+
}
1722+
1723+
private void GetScrollWarmupMargins(bool preferSymmetric, out int warmMarginTop, out int warmMarginBottom)
1724+
{
1725+
int fullMargin = ScrollWarmupMargin;
1726+
if (preferSymmetric || m_lastScrollWarmDirection == 0)
1727+
{
1728+
warmMarginTop = fullMargin;
1729+
warmMarginBottom = fullMargin;
1730+
return;
1731+
}
1732+
1733+
int trailingMargin = Math.Max(1, fullMargin / 2);
1734+
if (m_lastScrollWarmDirection > 0)
1735+
{
1736+
warmMarginTop = trailingMargin;
1737+
warmMarginBottom = fullMargin;
1738+
}
1739+
else
1740+
{
1741+
warmMarginTop = fullMargin;
1742+
warmMarginBottom = trailingMargin;
1743+
}
1744+
}
1745+
1746+
private static Rectangle OffsetRootRect(Rectangle rect, int dy)
1747+
{
1748+
rect.Offset(0, dy);
1749+
return rect;
1750+
}
1751+
1752+
protected virtual VwPrepDrawResult PrepareToDrawForScrollWarmup(Rectangle rcSrcRoot, Rectangle rcDstRoot)
1753+
{
1754+
VwPrepDrawResult xpdr = VwPrepDrawResult.kxpdrAdjust;
1755+
while (xpdr == VwPrepDrawResult.kxpdrAdjust)
1756+
xpdr = PrepareToDraw(rcSrcRoot, rcDstRoot);
1757+
1758+
return xpdr;
1759+
}
1760+
1761+
private void QueueDeferredScrollWarmup()
1762+
{
1763+
if (m_fDeferredScrollWarmupQueued || IsDisposed)
1764+
return;
1765+
if (!m_fDeferredScrollWarmupPending)
1766+
return;
1767+
if (!IsHandleCreated || !Visible || m_rootb == null || !AllowPainting)
1768+
return;
1769+
1770+
m_fDeferredScrollWarmupQueued = true;
1771+
BeginInvoke((MethodInvoker)delegate
1772+
{
1773+
m_fDeferredScrollWarmupQueued = false;
1774+
if (IsDisposed || !m_fDeferredScrollWarmupPending)
1775+
return;
1776+
if (!IsHandleCreated || !Visible || m_rootb == null || !AllowPainting || m_fInLayout)
1777+
return;
1778+
1779+
WarmScrollViewportIfNeeded(true);
1780+
});
16411781
}
16421782

16431783
/// -----------------------------------------------------------------------------------
@@ -2151,6 +2291,8 @@ public bool AllowPainting
21512291
Update();
21522292
Invalidate();
21532293
}
2294+
2295+
QueueDeferredScrollWarmup();
21542296
}
21552297
}
21562298
else
@@ -3287,6 +3429,8 @@ protected override void OnVisibleChanged(EventArgs e)
32873429
base.OnVisibleChanged(e);
32883430
if (Visible && m_fRootboxMade && m_rootb != null && m_fRefreshPending)
32893431
RefreshDisplay();
3432+
if (Visible)
3433+
QueueDeferredScrollWarmup();
32903434
}
32913435

32923436
/// <summary>
@@ -3854,7 +3998,10 @@ protected override void OnLayout(LayoutEventArgs levent)
38543998
using (new HoldGraphics(this))
38553999
{
38564000
if (DoLayout())
4001+
{
38574002
Invalidate();
4003+
QueueDeferredScrollWarmup();
4004+
}
38584005
}
38594006
}
38604007

@@ -5570,6 +5717,10 @@ protected bool UpdateScrollRange(int dxdRange, int dxdPos, int dydRange, int dyd
55705717
/// -----------------------------------------------------------------------------------
55715718
protected virtual bool DoLayout()
55725719
{
5720+
m_fDeferredScrollWarmupPending = true;
5721+
m_scrollWarmRangeTop = int.MinValue;
5722+
m_scrollWarmRangeBottom = int.MinValue;
5723+
55735724
if (DesignMode && !AllowPaintingInDesigner)
55745725
return false;
55755726

0 commit comments

Comments
 (0)