Browse Source

Show overlay layer when popup StaysOpen = false.

We need to stop events getting to parent window. Pointer capture won't work because this now needs an input event in order to take pointer capture, and filtering events on the parent window causes tooltips to continue tooltips to get stuck. Best solution would seem to be using an overlay layer.
pull/4099/head
Steven Kirk 6 years ago
parent
commit
2bdb914dd1
  1. 10
      src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
  2. 21
      src/Avalonia.Controls/Primitives/Popup.cs
  3. 25
      src/Avalonia.Controls/Primitives/VisualLayerManager.cs

10
src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs

@ -0,0 +1,10 @@
using System.Linq;
using Avalonia.Rendering;
using Avalonia.VisualTree;
namespace Avalonia.Controls.Primitives
{
public class LightDismissOverlayLayer : Border
{
}
}

21
src/Avalonia.Controls/Primitives/Popup.cs

@ -369,8 +369,6 @@ namespace Avalonia.Controls.Primitives
}
}
DeferCleanup(topLevel.AddDisposableHandler(PointerPressedEvent, PointerPressedOutside, RoutingStrategies.Tunnel));
DeferCleanup(InputManager.Instance?.Process.Subscribe(ListenForNonClientClick));
var cleanupPopup = Disposable.Create((popupHost, handlerCleanup), state =>
@ -384,6 +382,23 @@ namespace Avalonia.Controls.Primitives
state.popupHost.Dispose();
});
if (!StaysOpen)
{
var layerManager = placementTarget.FindAncestorOfType<VisualLayerManager>();
var dismissLayer = layerManager?.LightDismissOverlayLayer;
if (dismissLayer != null)
{
dismissLayer.IsVisible = true;
DeferCleanup(Disposable.Create(() => dismissLayer.IsVisible = false));
DeferCleanup(SubscribeToEventHandler<LightDismissOverlayLayer, EventHandler<PointerPressedEventArgs>>(
dismissLayer,
PointerPressedDismissOverlay,
(x, handler) => x.PointerPressed += handler,
(x, handler) => x.PointerPressed -= handler));
}
}
_openState = new PopupOpenState(topLevel, popupHost, cleanupPopup);
WindowManagerAddShadowHintChanged(popupHost, WindowManagerAddShadowHint);
@ -504,7 +519,7 @@ namespace Avalonia.Controls.Primitives
}
}
private void PointerPressedOutside(object sender, PointerPressedEventArgs e)
private void PointerPressedDismissOverlay(object sender, PointerPressedEventArgs e)
{
if (!StaysOpen && e.Source is IVisual v && !IsChildOrThis(v))
{

25
src/Avalonia.Controls/Primitives/VisualLayerManager.cs

@ -1,5 +1,6 @@
using System.Collections.Generic;
using Avalonia.LogicalTree;
using Avalonia.Media;
namespace Avalonia.Controls.Primitives
{
@ -7,7 +8,8 @@ namespace Avalonia.Controls.Primitives
{
private const int AdornerZIndex = int.MaxValue - 100;
private const int ChromeZIndex = int.MaxValue - 99;
private const int OverlayZIndex = int.MaxValue - 98;
private const int LightDismissOverlayZIndex = int.MaxValue - 98;
private const int OverlayZIndex = int.MaxValue - 97;
private ILogicalRoot _logicalRoot;
private readonly List<Control> _layers = new List<Control>();
@ -50,6 +52,27 @@ namespace Avalonia.Controls.Primitives
}
}
public LightDismissOverlayLayer LightDismissOverlayLayer
{
get
{
if (IsPopup)
return null;
var rv = FindLayer<LightDismissOverlayLayer>();
if (rv == null)
{
rv = new LightDismissOverlayLayer
{
Background = Brushes.Transparent,
IsVisible = false
};
AddLayer(rv, LightDismissOverlayZIndex);
}
return rv;
}
}
T FindLayer<T>() where T : class
{
foreach (var layer in _layers)

Loading…
Cancel
Save