Browse Source

Measure PopupRoot to MaxAutoSizeHint.

On win32 popup's don't receive `WM_GETMINMAXINFO` so instead query the monitor info for the max work area,
pull/3805/head
Steven Kirk 6 years ago
parent
commit
fc711e7c86
  1. 15
      src/Avalonia.Controls/Primitives/PopupRoot.cs
  2. 26
      src/Windows/Avalonia.Win32/PopupImpl.cs
  3. 4
      src/Windows/Avalonia.Win32/WindowImpl.cs
  4. 20
      tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs
  5. 1
      tests/Avalonia.UnitTests/MockWindowingPlatform.cs

15
src/Avalonia.Controls/Primitives/PopupRoot.cs

@ -119,7 +119,20 @@ namespace Avalonia.Controls.Primitives
protected override Size MeasureOverride(Size availableSize)
{
var measured = base.MeasureOverride(availableSize);
var maxAutoSize = PlatformImpl?.MaxAutoSizeHint ?? Size.Infinity;
var constraint = availableSize;
if (double.IsInfinity(constraint.Width))
{
constraint = constraint.WithWidth(maxAutoSize.Width);
}
if (double.IsInfinity(constraint.Height))
{
constraint = constraint.WithHeight(maxAutoSize.Height);
}
var measured = base.MeasureOverride(constraint);
var width = measured.Width;
var height = measured.Height;
var widthCache = Width;

26
src/Windows/Avalonia.Win32/PopupImpl.cs

@ -8,12 +8,35 @@ namespace Avalonia.Win32
class PopupImpl : WindowImpl, IPopupImpl
{
private bool _dropShadowHint = true;
private Size? _maxAutoSize;
public override void Show()
{
UnmanagedMethods.ShowWindow(Handle.Handle, UnmanagedMethods.ShowWindowCommand.ShowNoActivate);
}
public override Size MaxAutoSizeHint
{
get
{
if (_maxAutoSize is null)
{
var monitor = UnmanagedMethods.MonitorFromWindow(
Hwnd,
UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
if (monitor != IntPtr.Zero)
{
var info = UnmanagedMethods.MONITORINFO.Create();
UnmanagedMethods.GetMonitorInfo(monitor, ref info);
_maxAutoSize = info.rcWork.ToPixelRect().ToRect(Scaling).Size;
}
}
return _maxAutoSize ?? Size.Infinity;
}
}
protected override IntPtr CreateWindowOverride(ushort atom)
{
UnmanagedMethods.WindowStyles style =
@ -47,6 +70,9 @@ namespace Avalonia.Win32
{
switch ((UnmanagedMethods.WindowsMessage)msg)
{
case UnmanagedMethods.WindowsMessage.WM_DISPLAYCHANGE:
_maxAutoSize = null;
goto default;
case UnmanagedMethods.WindowsMessage.WM_MOUSEACTIVATE:
return (IntPtr)UnmanagedMethods.MouseActivate.MA_NOACTIVATE;
default:

4
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -169,7 +169,7 @@ namespace Avalonia.Win32
public IPlatformHandle Handle { get; private set; }
public Size MaxAutoSizeHint => new Size(_maxTrackSize.X / Scaling, _maxTrackSize.Y / Scaling);
public virtual Size MaxAutoSizeHint => new Size(_maxTrackSize.X / Scaling, _maxTrackSize.Y / Scaling);
public IMouseDevice MouseDevice => _mouseDevice;
@ -203,6 +203,8 @@ namespace Avalonia.Win32
public WindowTransparencyLevel TransparencyLevel { get; private set; }
protected IntPtr Hwnd => _hwnd;
public void SetTransparencyLevelHint (WindowTransparencyLevel transparencyLevel)
{
TransparencyLevel = EnableBlur(transparencyLevel);

20
tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
@ -181,18 +182,21 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
[Fact]
public void Child_Should_Be_Measured_With_Infinity()
public void Child_Should_Be_Measured_With_MaxAutoSizeHint()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var child = new ChildControl();
var window = new Window();
var target = CreateTarget(window);
var popupImpl = MockWindowingPlatform.CreatePopupMock(window.PlatformImpl);
popupImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1200, 1000));
var target = CreateTarget(window, popupImpl.Object);
target.Content = child;
target.Show();
Assert.Equal(Size.Infinity, child.MeasureSize);
Assert.Equal(1, child.MeasureSizes.Count);
Assert.Equal(new Size(1200, 1000), child.MeasureSizes[0]);
}
}
@ -210,7 +214,8 @@ namespace Avalonia.Controls.UnitTests.Primitives
target.Content = child;
target.Show();
Assert.Equal(new Size(500, 600), child.MeasureSize);
Assert.Equal(1, child.MeasureSizes.Count);
Assert.Equal(new Size(500, 600), child.MeasureSizes[0]);
}
}
@ -228,7 +233,8 @@ namespace Avalonia.Controls.UnitTests.Primitives
target.Content = child;
target.Show();
Assert.Equal(new Size(500, 600), child.MeasureSize);
Assert.Equal(1, child.MeasureSizes.Count);
Assert.Equal(new Size(500, 600), child.MeasureSizes[0]);
}
}
@ -365,11 +371,11 @@ namespace Avalonia.Controls.UnitTests.Primitives
private class ChildControl : Control
{
public Size MeasureSize { get; private set; }
public List<Size> MeasureSizes { get; } = new List<Size>();
protected override Size MeasureOverride(Size availableSize)
{
MeasureSize = availableSize;
MeasureSizes.Add(availableSize);
return base.MeasureOverride(availableSize);
}
}

1
tests/Avalonia.UnitTests/MockWindowingPlatform.cs

@ -80,6 +80,7 @@ namespace Avalonia.UnitTests
popupImpl.SetupAllProperties();
popupImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
popupImpl.Setup(x => x.MaxAutoSizeHint).Returns(s_screenSize);
popupImpl.Setup(x => x.Scaling).Returns(1);
popupImpl.Setup(x => x.PopupPositioner).Returns(positioner);

Loading…
Cancel
Save