Skip to content

Commit ee21a4e

Browse files
committed
fix(scrollviewer): [WASM] Make the SCP the "element which scrolls" (instead of the SV)
1 parent d05ebc4 commit ee21a4e

File tree

6 files changed

+54
-47
lines changed

6 files changed

+54
-47
lines changed

src/Uno.UI/Generated/3.0.0.0/Windows.UI.Xaml.Controls/ScrollContentPresenter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public bool CanHorizontallyScroll
5151
#endif
5252
// Skipping already declared property ExtentHeight
5353
// Skipping already declared property ExtentWidth
54-
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || false || __NETSTD_REFERENCE__ || false
54+
#if __ANDROID__ || __IOS__ || NET461 || false || false || __NETSTD_REFERENCE__ || false
5555
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__NETSTD_REFERENCE__", "__MACOS__")]
5656
public double HorizontalOffset
5757
{
@@ -61,7 +61,7 @@ public double HorizontalOffset
6161
}
6262
}
6363
#endif
64-
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || false || __NETSTD_REFERENCE__ || false
64+
#if __ANDROID__ || __IOS__ || NET461 || false || false || __NETSTD_REFERENCE__ || false
6565
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__NETSTD_REFERENCE__", "__MACOS__")]
6666
public double VerticalOffset
6767
{

src/Uno.UI/UI/Xaml/Controls/ScrollContentPresenter/ScrollContentPresenter.wasm.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ internal Size ScrollBarSize
3737

3838
public ScrollContentPresenter()
3939
{
40+
RegisterAsScrollPort(this);
4041
}
4142

4243
private void TryRegisterEvents(ScrollBarVisibility visibility)
@@ -143,6 +144,10 @@ public bool CanVerticallyScroll
143144
set { }
144145
}
145146

147+
public double HorizontalOffset { get; private set; }
148+
149+
public double VerticalOffset { get; private set; }
150+
146151
Size? IScrollContentPresenter.CustomContentExtent => null;
147152

148153
private protected override void OnLoaded()
@@ -248,11 +253,16 @@ private void OnScroll(object sender, EventArgs args)
248253
// (the SV updates mode is always sync when isIntermediate is false).
249254
var isIntermediate = false;
250255

251-
(TemplatedParent as ScrollViewer)?.OnScrollInternal(
252-
GetNativeHorizontalOffset(),
253-
GetNativeVerticalOffset(),
254-
isIntermediate
255-
);
256+
var horizontalOffset = GetNativeHorizontalOffset();
257+
var verticalOffset = GetNativeVerticalOffset();
258+
259+
HorizontalOffset = horizontalOffset;
260+
VerticalOffset = verticalOffset;
261+
262+
(TemplatedParent as ScrollViewer)?.OnScrollInternal(horizontalOffset, verticalOffset, isIntermediate);
263+
264+
ScrollOffsets = new Point(horizontalOffset, verticalOffset);
265+
InvalidateViewport();
256266
}
257267

258268
private double GetNativeHorizontalOffset()

src/Uno.UI/UI/Xaml/Controls/ScrollViewer/ScrollViewer.MuxInternal.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.Generic;
55
using System.Text;
6+
using Windows.Foundation;
67
using Windows.UI.Xaml.Automation.Peers;
78
using DirectUI;
89
using Uno.Disposables;
@@ -17,10 +18,30 @@ partial class ScrollViewer
1718

1819
internal bool m_templatedParentHandlesMouseButton;
1920

21+
// Indicates whether ScrollViewer should ignore mouse wheel scroll events (not zoom).
22+
internal bool ArePointerWheelEventsIgnored { get; set; } = false;
23+
internal bool IsInManipulation => IsInDirectManipulation || m_isInConstantVelocityPan;
24+
25+
/// <summary>
26+
/// Gets or set whether the <see cref="ScrollViewer"/> will allow scrolling outside of the ScrollViewer's Child bound.
27+
/// </summary>
28+
internal bool ForceChangeToCurrentView { get; set; } = false;
2029
internal bool IsInDirectManipulation { get; }
2130
internal bool TemplatedParentHandlesScrolling { get; set; }
2231
internal Func<AutomationPeer>? AutomationPeerFactoryIndex { get; set; }
2332

33+
internal bool BringIntoViewport(Rect bounds,
34+
bool skipDuringTouchContact,
35+
bool skipAnimationWhileRunning,
36+
bool animate)
37+
{
38+
#if __WASM__
39+
return ChangeView(bounds.X, bounds.Y, null, true);
40+
#else
41+
return ChangeView(bounds.X, bounds.Y, null, !animate);
42+
#endif
43+
}
44+
2445
internal void SetDirectManipulationStateChangeHandler(IDirectManipulationStateChangeHandler? handler)
2546
{
2647
_directManipulationHandlerSubscription?.Dispose();

src/Uno.UI/UI/Xaml/Controls/ScrollViewer/ScrollViewer.cs

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#pragma warning disable CS0067
33
#endif
44

5+
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER && !__WASM__
6+
#define IS_SCROLL_PORT
7+
#endif
8+
59
#nullable enable
610

711
using System;
@@ -119,7 +123,7 @@ public ScrollViewer()
119123
{
120124
DefaultStyleKey = typeof(ScrollViewer);
121125

122-
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER
126+
#if IS_SCROLL_PORT
123127
// On Skia, the Scrolling is managed by the ScrollContentPresenter (as UWP), which is flagged as IsScrollPort.
124128
// Note: We should still add support for the zoom factor ... which is not yet supported on Skia.
125129
// Note 2: This as direct consequences in UIElement.GetTransform and VisualTreeHelper.SearchDownForTopMostElementAt
@@ -634,7 +638,6 @@ public double HorizontalOffset
634638
/// </summary>
635639
internal bool ComputedIsVerticalScrollEnabled { get; private set; } = false;
636640

637-
638641
internal double MinHorizontalOffset => 0;
639642

640643
internal double MinVerticalOffset => 0;
@@ -1305,7 +1308,7 @@ private void Update(bool isIntermediate)
13051308

13061309
UpdatePartial(isIntermediate);
13071310

1308-
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER
1311+
#if IS_SCROLL_PORT
13091312
// Effective viewport support
13101313
ScrollOffsets = new Point(_pendingHorizontalOffset, _pendingVerticalOffset);
13111314
InvalidateViewport();
@@ -1316,6 +1319,12 @@ private void Update(bool isIntermediate)
13161319

13171320
partial void UpdatePartial(bool isIntermediate);
13181321

1322+
public void ScrollToHorizontalOffset(double offset)
1323+
=> ChangeView(offset, null, null, false);
1324+
1325+
public void ScrollToVerticalOffset(double offset)
1326+
=> ChangeView(null, offset, null, false);
1327+
13191328
/// <summary>
13201329
/// Causes the ScrollViewer to load a new view into the viewport using the specified offsets and zoom factor, and optionally disables scrolling animation.
13211330
/// </summary>
@@ -1493,38 +1502,5 @@ private void HideScrollBarSeparator(object sender, PointerRoutedEventArgs e) //
14931502
}
14941503
}
14951504
#endregion
1496-
1497-
public void ScrollToHorizontalOffset(double offset)
1498-
{
1499-
_ = ChangeView(offset, null, null, false);
1500-
}
1501-
1502-
public void ScrollToVerticalOffset(double offset)
1503-
{
1504-
_ = ChangeView(null, offset, null, false);
1505-
}
1506-
1507-
// Indicates whether ScrollViewer should ignore mouse wheel scroll events (not zoom).
1508-
public bool ArePointerWheelEventsIgnored { get; set; } = false;
1509-
1510-
internal bool BringIntoViewport(Rect bounds,
1511-
bool skipDuringTouchContact,
1512-
bool skipAnimationWhileRunning,
1513-
bool animate)
1514-
{
1515-
#if __WASM__
1516-
return ChangeView(bounds.X, bounds.Y, null, true);
1517-
#else
1518-
return ChangeView(bounds.X, bounds.Y, null, !animate);
1519-
#endif
1520-
}
1521-
1522-
internal bool IsInManipulation => IsInDirectManipulation || m_isInConstantVelocityPan;
1523-
1524-
/// <summary>
1525-
/// Gets or set whether the <see cref="ScrollViewer"/> will allow scrolling outside of the ScrollViewer's Child bound.
1526-
/// </summary>
1527-
internal bool ForceChangeToCurrentView { get; set; } = false;
1528-
15291505
}
15301506
}

src/Uno.UI/UI/Xaml/Media/VisualTreeHelper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ private static (UIElement? element, Branch? stale) SearchDownForTopMostElementAt
389389
renderingBounds = parentToElement.Transform(renderingBounds);
390390
}
391391

392-
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER
392+
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER && !__WASM__
393393
// On Skia, the Scrolling is managed by the ScrollContentPresenter (as UWP), which is flagged as IsScrollPort.
394394
// Note: We should still add support for the zoom factor ... which is not yet supported on Skia.
395395
if (element is ScrollViewer sv)
@@ -410,7 +410,7 @@ private static (UIElement? element, Branch? stale) SearchDownForTopMostElementAt
410410
else
411411
#endif
412412
#if !__MACOS__ // On macOS the SCP is using RenderTransforms for scrolling which has already been included.
413-
if (element.IsScrollPort)
413+
if (element.IsScrollPort) // Managed SCP or custom scroller
414414
{
415415
posRelToElement.X += element.ScrollOffsets.X;
416416
posRelToElement.Y += element.ScrollOffsets.Y;

src/Uno.UI/UI/Xaml/UIElement.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ internal static Matrix3x2 GetTransform(UIElement from, UIElement to)
344344
offsetY = layoutSlot.Y;
345345
}
346346

347-
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER
347+
#if !UNO_HAS_MANAGED_SCROLL_PRESENTER && !__WASM__
348348
// On Skia, the Scrolling is managed by the ScrollContentPresenter (as UWP), which is flagged as IsScrollPort.
349349
// Note: We should still add support for the zoom factor ... which is not yet supported on Skia.
350350
if (elt is ScrollViewer sv
@@ -372,7 +372,7 @@ internal static Matrix3x2 GetTransform(UIElement from, UIElement to)
372372
#if !__MACOS__ // On macOS the SCP is using RenderTransforms for scrolling which has already been included.
373373
if (elt.IsScrollPort
374374
// Don't adjust for scroll offsets if it's the scroll port itself calling TransformToVisual, only for ancestors
375-
&& elt != from) // Custom scroller
375+
&& elt != from) // Managed SCP or custom scroller
376376
{
377377
offsetX -= elt.ScrollOffsets.X;
378378
offsetY -= elt.ScrollOffsets.Y;

0 commit comments

Comments
 (0)