|
|
@@ -1,12 +1,10 @@
|
|
|
using System;
|
|
|
-using System.Diagnostics;
|
|
|
using System.Linq;
|
|
|
using System.Reactive.Disposables;
|
|
|
using Avalonia.Controls.Presenters;
|
|
|
using Avalonia.Controls.Primitives.PopupPositioning;
|
|
|
using Avalonia.Input;
|
|
|
using Avalonia.Input.Raw;
|
|
|
-using Avalonia.Interactivity;
|
|
|
using Avalonia.LogicalTree;
|
|
|
using Avalonia.Metadata;
|
|
|
using Avalonia.Platform;
|
|
|
@@ -86,6 +84,9 @@ namespace Avalonia.Controls.Primitives
|
|
|
AvaloniaProperty.Register<Popup, bool>(nameof(ObeyScreenEdges), true);
|
|
|
#pragma warning restore 618
|
|
|
|
|
|
+ public static readonly StyledProperty<bool> OverlayDismissEventPassThroughProperty =
|
|
|
+ AvaloniaProperty.Register<Popup, bool>(nameof(OverlayDismissEventPassThrough));
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="HorizontalOffset"/> property.
|
|
|
/// </summary>
|
|
|
@@ -138,7 +139,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// <summary>
|
|
|
/// Raised when the popup closes.
|
|
|
/// </summary>
|
|
|
- public event EventHandler<PopupClosedEventArgs>? Closed;
|
|
|
+ public event EventHandler<EventArgs>? Closed;
|
|
|
|
|
|
/// <summary>
|
|
|
/// Raised when the popup opens.
|
|
|
@@ -179,6 +180,9 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// <summary>
|
|
|
/// Gets or sets a value that determines how the <see cref="Popup"/> can be dismissed.
|
|
|
/// </summary>
|
|
|
+ /// <remarks>
|
|
|
+ /// Light dismiss is when the user taps on any area other than the popup.
|
|
|
+ /// </remarks>
|
|
|
public bool IsLightDismissEnabled
|
|
|
{
|
|
|
get => GetValue(IsLightDismissEnabledProperty);
|
|
|
@@ -266,6 +270,22 @@ namespace Avalonia.Controls.Primitives
|
|
|
set => SetValue(ObeyScreenEdgesProperty, value);
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Gets or sets a value indicating whether the event that closes the popup is passed
|
|
|
+ /// through to the parent window.
|
|
|
+ /// </summary>
|
|
|
+ /// <remarks>
|
|
|
+ /// When <see cref="IsLightDismissEnabled"/> is set to true, clicks outside the the popup
|
|
|
+ /// cause the popup to close. When <see cref="OverlayDismissEventPassThrough"/> is set to
|
|
|
+ /// false, these clicks will be handled by the popup and not be registered by the parent
|
|
|
+ /// window. When set to true, the events will be passed through to the parent window.
|
|
|
+ /// </remarks>
|
|
|
+ public bool OverlayDismissEventPassThrough
|
|
|
+ {
|
|
|
+ get => GetValue(OverlayDismissEventPassThroughProperty);
|
|
|
+ set => SetValue(OverlayDismissEventPassThroughProperty, value);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Gets or sets the Horizontal offset of the popup in relation to the <see cref="PlacementTarget"/>.
|
|
|
/// </summary>
|
|
|
@@ -384,7 +404,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
|
|
|
if (parentPopupRoot?.Parent is Popup popup)
|
|
|
{
|
|
|
- DeferCleanup(SubscribeToEventHandler<Popup, EventHandler<PopupClosedEventArgs>>(popup, ParentClosed,
|
|
|
+ DeferCleanup(SubscribeToEventHandler<Popup, EventHandler<EventArgs>>(popup, ParentClosed,
|
|
|
(x, handler) => x.Closed += handler,
|
|
|
(x, handler) => x.Closed -= handler));
|
|
|
}
|
|
|
@@ -436,7 +456,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// <summary>
|
|
|
/// Closes the popup.
|
|
|
/// </summary>
|
|
|
- public void Close() => CloseCore(null);
|
|
|
+ public void Close() => CloseCore();
|
|
|
|
|
|
/// <summary>
|
|
|
/// Measures the control.
|
|
|
@@ -506,7 +526,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void CloseCore(EventArgs? closeEvent)
|
|
|
+ private void CloseCore()
|
|
|
{
|
|
|
if (_openState is null)
|
|
|
{
|
|
|
@@ -526,7 +546,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
IsOpen = false;
|
|
|
}
|
|
|
|
|
|
- Closed?.Invoke(this, new PopupClosedEventArgs(closeEvent));
|
|
|
+ Closed?.Invoke(this, EventArgs.Empty);
|
|
|
}
|
|
|
|
|
|
private void ListenForNonClientClick(RawInputEventArgs e)
|
|
|
@@ -535,7 +555,7 @@ namespace Avalonia.Controls.Primitives
|
|
|
|
|
|
if (IsLightDismissEnabled && mouse?.Type == RawPointerEventType.NonClientLeftButtonDown)
|
|
|
{
|
|
|
- CloseCore(e);
|
|
|
+ CloseCore();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -543,7 +563,28 @@ namespace Avalonia.Controls.Primitives
|
|
|
{
|
|
|
if (IsLightDismissEnabled && e.Source is IVisual v && !IsChildOrThis(v))
|
|
|
{
|
|
|
- CloseCore(e);
|
|
|
+ CloseCore();
|
|
|
+
|
|
|
+ if (OverlayDismissEventPassThrough)
|
|
|
+ {
|
|
|
+ PassThroughEvent(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void PassThroughEvent(PointerPressedEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.Source is LightDismissOverlayLayer layer &&
|
|
|
+ layer.GetVisualRoot() is IInputElement root)
|
|
|
+ {
|
|
|
+ var p = e.GetCurrentPoint(root);
|
|
|
+ var hit = root.InputHitTest(p.Position, x => x != layer);
|
|
|
+
|
|
|
+ if (hit != null)
|
|
|
+ {
|
|
|
+ hit.RaiseEvent(e);
|
|
|
+ e.Handled = true;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|