Browse Source

Merge branch 'master' into fixes/3094-focusable-hang

pull/3096/head
danwalmsley 7 years ago
committed by GitHub
parent
commit
c1d5e04f6f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      build/Base.props
  2. 15
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
  3. 10
      src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
  4. 9
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  5. 26
      src/Windows/Avalonia.Win32/ScreenImpl.cs
  6. 12
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DeferredDrawingContextImplTests.cs
  7. 3
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs
  8. 8
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs

1
build/Base.props

@ -1,5 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.6.0" />
</ItemGroup>
</Project>

15
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@ -148,6 +148,19 @@ namespace Avalonia.Rendering.SceneGraph
return (VisualNode)node;
}
private static object GetOrCreateChildNode(Scene scene, IVisual child, VisualNode parent)
{
var result = (VisualNode)scene.FindNode(child);
if (result != null && result.Parent != parent)
{
Deindex(scene, result);
result = null;
}
return result ?? CreateNode(scene, child, parent);
}
private static void Update(DrawingContext context, Scene scene, VisualNode node, Rect clip, bool forceRecurse)
{
var visual = node.Visual;
@ -231,7 +244,7 @@ namespace Avalonia.Rendering.SceneGraph
{
foreach (var child in visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance))
{
var childNode = scene.FindNode(child) ?? CreateNode(scene, child, node);
var childNode = GetOrCreateChildNode(scene, child, node);
Update(context, scene, (VisualNode)childNode, clip, forceRecurse);
}

10
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@ -119,6 +119,11 @@ namespace Avalonia.Rendering.SceneGraph
throw new ObjectDisposedException("Visual node for {node.Visual}");
}
if (child.Parent != this)
{
throw new AvaloniaInternalException("VisualNode added to wrong parent.");
}
EnsureChildrenCreated();
_children.Add(child);
}
@ -155,6 +160,11 @@ namespace Avalonia.Rendering.SceneGraph
throw new ObjectDisposedException("Visual node for {node.Visual}");
}
if (node.Parent != this)
{
throw new AvaloniaInternalException("VisualNode added to wrong parent.");
}
EnsureChildrenCreated();
_children[index] = node;
}

9
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -1031,6 +1031,9 @@ namespace Avalonia.Win32.Interop
[DllImport("shcore.dll")]
public static extern long GetDpiForMonitor(IntPtr hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY);
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, DEVICECAP nIndex);
[DllImport("shcore.dll")]
public static extern void GetScaleFactorForMonitor(IntPtr hMon, out uint pScale);
@ -1147,6 +1150,12 @@ namespace Avalonia.Win32.Interop
}
}
public enum DEVICECAP
{
HORZRES = 8,
DESKTOPHORZRES = 118
}
public enum PROCESS_DPI_AWARENESS
{
PROCESS_DPI_UNAWARE = 0,

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

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
using static Avalonia.Win32.Interop.UnmanagedMethods;
namespace Avalonia.Win32
@ -28,9 +29,28 @@ namespace Avalonia.Win32
(IntPtr monitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr data) =>
{
MONITORINFO monitorInfo = MONITORINFO.Create();
if (GetMonitorInfo(monitor,ref monitorInfo))
if (GetMonitorInfo(monitor, ref monitorInfo))
{
GetDpiForMonitor(monitor, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out var x, out _);
var dpi = 1.0;
var shcore = LoadLibrary("shcore.dll");
var method = GetProcAddress(shcore, nameof(GetDpiForMonitor));
if (method != IntPtr.Zero)
{
GetDpiForMonitor(monitor, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out var x, out _);
dpi = (double)x;
}
else
{
var hdc = GetDC(IntPtr.Zero);
double virtW = GetDeviceCaps(hdc, DEVICECAP.HORZRES);
double physW = GetDeviceCaps(hdc, DEVICECAP.DESKTOPHORZRES);
dpi = (96d * physW / virtW);
ReleaseDC(IntPtr.Zero, hdc);
}
RECT bounds = monitorInfo.rcMonitor;
RECT workingArea = monitorInfo.rcWork;
@ -40,7 +60,7 @@ namespace Avalonia.Win32
new PixelRect(workingArea.left, workingArea.top, workingArea.right - workingArea.left,
workingArea.bottom - workingArea.top);
screens[index] =
new WinScreen((double)x / 96.0d, avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1,
new WinScreen(dpi / 96.0d, avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1,
monitor);
index++;
}

12
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DeferredDrawingContextImplTests.cs

@ -17,7 +17,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Should_Add_VisualNode()
{
var parent = new VisualNode(new TestRoot(), null);
var child = new VisualNode(Mock.Of<IVisual>(), null);
var child = new VisualNode(Mock.Of<IVisual>(), parent);
var layers = new SceneLayers(parent.Visual);
var target = new DeferredDrawingContextImpl(null, layers);
@ -32,7 +32,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Should_Not_Replace_Identical_VisualNode()
{
var parent = new VisualNode(new TestRoot(), null);
var child = new VisualNode(Mock.Of<IVisual>(), null);
var child = new VisualNode(Mock.Of<IVisual>(), parent);
var layers = new SceneLayers(parent.Visual);
parent.AddChild(child);
@ -50,8 +50,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Should_Replace_Different_VisualNode()
{
var parent = new VisualNode(new TestRoot(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), null);
var child2 = new VisualNode(Mock.Of<IVisual>(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), parent);
var child2 = new VisualNode(Mock.Of<IVisual>(), parent);
var layers = new SceneLayers(parent.Visual);
parent.AddChild(child1);
@ -78,8 +78,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
var layers = new SceneLayers(root);
var target = new DeferredDrawingContextImpl(null, layers);
var child1 = new VisualNode(Mock.Of<IVisual>(), null) { LayerRoot = root };
var child2 = new VisualNode(Mock.Of<IVisual>(), null) { LayerRoot = root };
var child1 = new VisualNode(Mock.Of<IVisual>(), node) { LayerRoot = root };
var child2 = new VisualNode(Mock.Of<IVisual>(), node) { LayerRoot = root };
target.BeginUpdate(node);
using (target.BeginUpdate(child1)) { }

3
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs

@ -620,10 +620,9 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
border1.IsVisible = false;
scene = scene.CloneScene();
var panelNode = (VisualNode)scene.FindNode(panel);
sceneBuilder.Update(scene, decorator);
var panelNode = (VisualNode)scene.FindNode(panel);
Assert.Equal(2, panelNode.Children.Count);
Assert.False(panelNode.Children[0].Disposed);
Assert.False(panelNode.Children[1].Disposed);

8
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs

@ -24,7 +24,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
var node = new VisualNode(Mock.Of<IVisual>(), null);
var collection = node.Children;
node.AddChild(Mock.Of<IVisualNode>());
node.AddChild(Mock.Of<IVisualNode>(x => x.Parent == node));
Assert.NotSame(collection, node.Children);
}
@ -106,9 +106,9 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void TrimChildren_Should_Work_Correctly()
{
var parent = new VisualNode(Mock.Of<IVisual>(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), null);
var child2 = new VisualNode(Mock.Of<IVisual>(), null);
var child3 = new VisualNode(Mock.Of<IVisual>(), null);
var child1 = new VisualNode(Mock.Of<IVisual>(), parent);
var child2 = new VisualNode(Mock.Of<IVisual>(), parent);
var child3 = new VisualNode(Mock.Of<IVisual>(), parent);
parent.AddChild(child1);
parent.AddChild(child2);

Loading…
Cancel
Save