Skip to content

Commit

Permalink
chore: Adjust Popup fix for Skia and WASM
Browse files Browse the repository at this point in the history
On these platforms, changing the real Parent to be other than the visual parent breaks the current pointer implementation. As a workaround, we just override the publicly-visible FE.Parent value, without actually changing Store.Parent.
  • Loading branch information
davidjohnoliver committed May 14, 2021
1 parent aa1755a commit cbbb7d7
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 6 deletions.
6 changes: 3 additions & 3 deletions src/Uno.UI/UI/Xaml/Controls/Popup/PopupPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ protected override Size MeasureOverride(Size availableSize)

if (this.Log().IsEnabled(LogLevel.Debug))
{
this.Log().LogDebug($"Measured PopupPanel #={GetHashCode()} ({(Popup.CustomLayouter == null?"":"**using custom layouter**")}) DC={Popup.DataContext} child={child} offset={Popup.HorizontalOffset},{Popup.VerticalOffset} availableSize={availableSize} measured={_lastMeasuredSize}");
this.Log().LogDebug($"Measured PopupPanel #={GetHashCode()} ({(Popup.CustomLayouter == null ? "" : "**using custom layouter**")}) DC={Popup.DataContext} child={child} offset={Popup.HorizontalOffset},{Popup.VerticalOffset} availableSize={availableSize} measured={_lastMeasuredSize}");
}

// Note that we return the availableSize and not the _lastMeasuredSize. This is because this
Expand Down Expand Up @@ -179,13 +179,13 @@ private protected override void OnLoaded()
base.OnLoaded();
// Set Parent to the Popup, to obtain the same behavior as UWP that the Popup (and therefore the rest of the main visual tree)
// is reachable by scaling the combined Parent/GetVisualParent() hierarchy.
this.SetParent(Popup);
this.SetLogicalParent(Popup);
}

private protected override void OnUnloaded()
{
base.OnUnloaded();
this.SetParent(null);
this.SetLogicalParent(null);
}
}
}
17 changes: 16 additions & 1 deletion src/Uno.UI/UI/Xaml/DependencyObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ internal static bool HasParent(this object dependencyObject, DependencyObject se
var parent = dependencyObject.GetParent();
while (parent != null)
{
if(ReferenceEquals(parent, searchedParent))
if (ReferenceEquals(parent, searchedParent))
{
return true;
}
Expand All @@ -127,6 +127,21 @@ internal static void SetParent(this object dependencyObject, object parent)
GetStore(dependencyObject).Parent = parent;
}

internal static void SetLogicalParent(this FrameworkElement element, DependencyObject logicalParent)
{
#if UNO_HAS_MANAGED_POINTERS || __WASM__ // WASM has managed-esque pointers

// UWP distinguishes between the 'logical parent' (or inheritance parent) and the 'visual parent' of an element. Uno already
// recognises this distinction on some targets, but for targets using CoerceHitTestVisibility() for hit testing, the pointer
// implementation depends upon the logical parent (ie DepObjStore.Parent) being identical to the visual parent, because it
// piggybacks on the DP inheritance mechanism. Therefore we use LogicalParentOverride as a workaround to modify the publicly-visible
// FrameworkElement.Parent without affecting DP propagation.
element.LogicalParentOverride = logicalParent;
#else
SetParent(element, logicalParent);
#endif
}

/// <summary>
/// Creates a SetValue precedence scoped override. All calls to SetValue
/// on the specified instance will be set to the specified precedence.
Expand Down
16 changes: 15 additions & 1 deletion src/Uno.UI/UI/Xaml/FrameworkElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,21 @@ Windows.UI.Xaml.ResourceDictionary Resources
#if __ANDROID__
new
#endif
DependencyObject Parent => ((IDependencyObjectStoreProvider)this).Store.Parent as DependencyObject;
DependencyObject Parent =>
#if UNO_HAS_MANAGED_POINTERS || __WASM__
LogicalParentOverride ??
#endif
((IDependencyObjectStoreProvider)this).Store.Parent as DependencyObject;


#if UNO_HAS_MANAGED_POINTERS || __WASM__
/// <summary>
/// Allows to override the publicly-visible <see cref="Parent"/> without modifying DP propagation.
/// </summary>
internal DependencyObject LogicalParentOverride { get; set; }

internal UIElement VisualParent => ((IDependencyObjectStoreProvider)this).Store.Parent as UIElement;
#endif

private bool _isParsing;
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/UIElementExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static partial class UIElementExtensions
/// <summary>
/// Get the parent view in the visual tree.
/// </summary>
public static UIElement GetVisualTreeParent(this UIElement uiElement) => (uiElement as FrameworkElement)?.Parent as UIElement;
public static UIElement GetVisualTreeParent(this UIElement uiElement) => (uiElement as FrameworkElement)?.VisualParent;
}
}
#endif

0 comments on commit cbbb7d7

Please sign in to comment.