Browse Source

Merge branch 'master' into wrappanel-add-itemwidth-itemheight-properties

pull/3008/head
danwalmsley 7 years ago
committed by GitHub
parent
commit
92b82b7a39
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      native/Avalonia.Native/inc/avalonia-native.h
  2. 2
      native/Avalonia.Native/src/OSX/Screens.mm
  3. 24
      native/Avalonia.Native/src/OSX/window.mm
  4. 7
      samples/ControlCatalog/Pages/ScreenPage.cs
  5. 7
      src/Avalonia.Animation/Animatable.cs
  6. 5
      src/Avalonia.Controls/Platform/Screen.cs
  7. 6
      src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositionerPopupImplHelper.cs
  8. 7
      src/Avalonia.Controls/Repeater/ViewManager.cs
  9. 2
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  10. 1
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  11. 18
      src/Avalonia.Native/OsxManagedPopupPositionerPopupImplHelper.cs
  12. 2
      src/Avalonia.Native/PopupImpl.cs
  13. 1
      src/Avalonia.Native/ScreenImpl.cs
  14. 9
      src/Avalonia.Native/WindowImplBase.cs
  15. 4
      src/Avalonia.Themes.Default/ProgressBar.xaml
  16. 2
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  17. 15
      src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
  18. 2
      src/Avalonia.X11/X11Screens.cs
  19. 16
      src/Avalonia.X11/X11Window.cs
  20. 1
      src/Shared/PlatformSupport/AssetLoader.cs
  21. 4
      src/Windows/Avalonia.Win32/ScreenImpl.cs
  22. 2
      src/Windows/Avalonia.Win32/WinScreen.cs
  23. 2
      tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
  24. 4
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  25. 50
      tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs
  26. 58
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs
  27. 2
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs

2
native/Avalonia.Native/inc/avalonia-native.h

@ -52,6 +52,7 @@ struct AvnScreen
{ {
AvnRect Bounds; AvnRect Bounds;
AvnRect WorkingArea; AvnRect WorkingArea;
float PixelDensity;
bool Primary; bool Primary;
}; };
@ -187,7 +188,6 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown
virtual HRESULT Close() = 0; virtual HRESULT Close() = 0;
virtual HRESULT Activate () = 0; virtual HRESULT Activate () = 0;
virtual HRESULT GetClientSize(AvnSize*ret) = 0; virtual HRESULT GetClientSize(AvnSize*ret) = 0;
virtual HRESULT GetMaxClientSize(AvnSize* ret) = 0;
virtual HRESULT GetScaling(double*ret)=0; virtual HRESULT GetScaling(double*ret)=0;
virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) = 0; virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) = 0;
virtual HRESULT Resize(double width, double height) = 0; virtual HRESULT Resize(double width, double height) = 0;

2
native/Avalonia.Native/src/OSX/Screens.mm

@ -38,6 +38,8 @@ class Screens : public ComSingleObject<IAvnScreens, &IID_IAvnScreens>
ret->WorkingArea.Height = [screen visibleFrame].size.height; ret->WorkingArea.Height = [screen visibleFrame].size.height;
ret->WorkingArea.Width = [screen visibleFrame].size.width; ret->WorkingArea.Width = [screen visibleFrame].size.width;
ret->PixelDensity = [screen backingScaleFactor];
ret->Primary = index == 0; ret->Primary = index == 0;
return S_OK; return S_OK;

24
native/Avalonia.Native/src/OSX/window.mm

@ -54,7 +54,6 @@ public:
FORWARD_IUNKNOWN() FORWARD_IUNKNOWN()
virtual ~WindowBaseImpl() virtual ~WindowBaseImpl()
{ {
NSDebugLog(@"~WindowBaseImpl()");
View = NULL; View = NULL;
Window = NULL; Window = NULL;
} }
@ -161,22 +160,6 @@ public:
} }
} }
virtual HRESULT GetMaxClientSize(AvnSize* ret) override
{
@autoreleasepool
{
if(ret == nullptr)
return E_POINTER;
auto size = [NSScreen.screens objectAtIndex:0].frame.size;
ret->Height = size.height;
ret->Width = size.width;
return S_OK;
}
}
virtual HRESULT GetScaling (double* ret) override virtual HRESULT GetScaling (double* ret) override
{ {
@autoreleasepool @autoreleasepool
@ -413,8 +396,8 @@ private:
INHERIT_INTERFACE_MAP(WindowBaseImpl) INHERIT_INTERFACE_MAP(WindowBaseImpl)
INTERFACE_MAP_ENTRY(IAvnWindow, IID_IAvnWindow) INTERFACE_MAP_ENTRY(IAvnWindow, IID_IAvnWindow)
END_INTERFACE_MAP() END_INTERFACE_MAP()
virtual ~WindowImpl(){ virtual ~WindowImpl()
NSDebugLog(@"~WindowImpl"); {
} }
ComPtr<IAvnWindowEvents> WindowEvents; ComPtr<IAvnWindowEvents> WindowEvents;
@ -662,10 +645,8 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)dealloc - (void)dealloc
{ {
NSDebugLog(@"AvnView dealloc");
} }
- (void)onClosed - (void)onClosed
{ {
_parent = NULL; _parent = NULL;
@ -1065,7 +1046,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
- (void)dealloc - (void)dealloc
{ {
NSDebugLog(@"AvnWindow dealloc");
} }
- (void)pollModalSession:(nonnull NSModalSession)session - (void)pollModalSession:(nonnull NSModalSession)session

7
samples/ControlCatalog/Pages/ScreenPage.cs

@ -57,12 +57,15 @@ namespace ControlCatalog.Pages
text.Text = $"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}"; text.Text = $"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text); context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
text.Text = $"Scaling: {screen.PixelDensity * 100}%";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
text.Text = $"Primary: {screen.Primary}"; text.Text = $"Primary: {screen.Primary}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text); context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}"; text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text); context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
} }
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10)); context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10));

7
src/Avalonia.Animation/Animatable.cs

@ -55,6 +55,11 @@ namespace Avalonia.Animation
} }
set set
{ {
if (value is null)
return;
if (_previousTransitions is null)
_previousTransitions = new Dictionary<AvaloniaProperty, IDisposable>();
SetAndRaise(TransitionsProperty, ref _transitions, value); SetAndRaise(TransitionsProperty, ref _transitions, value);
} }
@ -70,7 +75,7 @@ namespace Avalonia.Animation
if (_transitions is null || _previousTransitions is null || e.Priority == BindingPriority.Animation) return; if (_transitions is null || _previousTransitions is null || e.Priority == BindingPriority.Animation) return;
// PERF-SENSITIVE: Called on every property change. Don't use LINQ here (too many allocations). // PERF-SENSITIVE: Called on every property change. Don't use LINQ here (too many allocations).
foreach (var transition in Transitions) foreach (var transition in _transitions)
{ {
if (transition.Property == e.Property) if (transition.Property == e.Property)
{ {

5
src/Avalonia.Controls/Platform/Screen.cs

@ -2,14 +2,17 @@
{ {
public class Screen public class Screen
{ {
public double PixelDensity { get; }
public PixelRect Bounds { get; } public PixelRect Bounds { get; }
public PixelRect WorkingArea { get; } public PixelRect WorkingArea { get; }
public bool Primary { get; } public bool Primary { get; }
public Screen(PixelRect bounds, PixelRect workingArea, bool primary) public Screen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool primary)
{ {
this.PixelDensity = pixelDensity;
this.Bounds = bounds; this.Bounds = bounds;
this.WorkingArea = workingArea; this.WorkingArea = workingArea;
this.Primary = primary; this.Primary = primary;

6
src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositionerPopupImplHelper.cs

@ -32,7 +32,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
{ {
// Popup positioner operates with abstract coordinates, but in our case they are pixel ones // Popup positioner operates with abstract coordinates, but in our case they are pixel ones
var point = _parent.PointToScreen(default); var point = _parent.PointToScreen(default);
var size = PixelSize.FromSize(_parent.ClientSize, _parent.Scaling); var size = TranslateSize(_parent.ClientSize);
return new Rect(point.X, point.Y, size.Width, size.Height); return new Rect(point.X, point.Y, size.Width, size.Height);
} }
@ -43,8 +43,8 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
_moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _parent.Scaling); _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _parent.Scaling);
} }
public Point TranslatePoint(Point pt) => pt * _parent.Scaling; public virtual Point TranslatePoint(Point pt) => pt * _parent.Scaling;
public Size TranslateSize(Size size) => size * _parent.Scaling; public virtual Size TranslateSize(Size size) => size * _parent.Scaling;
} }
} }

7
src/Avalonia.Controls/Repeater/ViewManager.cs

@ -128,8 +128,7 @@ namespace Avalonia.Controls
private void MoveFocusFromClearedIndex(int clearedIndex) private void MoveFocusFromClearedIndex(int clearedIndex)
{ {
IControl focusedChild = null; var focusCandidate = FindFocusCandidate(clearedIndex, out var focusedChild);
var focusCandidate = FindFocusCandidate(clearedIndex, focusedChild);
if (focusCandidate != null) if (focusCandidate != null)
{ {
focusCandidate.Focus(); focusCandidate.Focus();
@ -145,7 +144,7 @@ namespace Avalonia.Controls
} }
} }
IControl FindFocusCandidate(int clearedIndex, IControl focusedChild) IControl FindFocusCandidate(int clearedIndex, out IControl focusedChild)
{ {
// Walk through all the children and find elements with index before and after the cleared index. // Walk through all the children and find elements with index before and after the cleared index.
// Note that during a delete the next element would now have the same index. // Note that during a delete the next element would now have the same index.
@ -183,7 +182,7 @@ namespace Avalonia.Controls
// TODO: Find the next element if one exists, if not use the previous element. // TODO: Find the next element if one exists, if not use the previous element.
// If the container itself is not focusable, find a descendent that is. // If the container itself is not focusable, find a descendent that is.
focusedChild = nextElement;
return nextElement; return nextElement;
} }

2
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -178,6 +178,6 @@ namespace Avalonia.DesignerSupport.Remote
public int ScreenCount => 1; public int ScreenCount => 1;
public IReadOnlyList<Screen> AllScreens { get; } = public IReadOnlyList<Screen> AllScreens { get; } =
new Screen[] { new Screen(new PixelRect(0, 0, 4000, 4000), new PixelRect(0, 0, 4000, 4000), true) }; new Screen[] { new Screen(1, new PixelRect(0, 0, 4000, 4000), new PixelRect(0, 0, 4000, 4000), true) };
} }
} }

1
src/Avalonia.Native/AvaloniaNativePlatform.cs

@ -1,7 +1,6 @@
// Copyright (c) The Avalonia Project. All rights reserved. // Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Input; using Avalonia.Input;

18
src/Avalonia.Native/OsxManagedPopupPositionerPopupImplHelper.cs

@ -0,0 +1,18 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Platform;
namespace Avalonia.Native
{
class OsxManagedPopupPositionerPopupImplHelper : ManagedPopupPositionerPopupImplHelper
{
public OsxManagedPopupPositionerPopupImplHelper(IWindowBaseImpl parent, MoveResizeDelegate moveResize) : base(parent, moveResize)
{
}
public override Point TranslatePoint(Point pt) => pt;
public override Size TranslateSize(Size size) => size;
}
}

2
src/Avalonia.Native/PopupImpl.cs

@ -22,7 +22,7 @@ namespace Avalonia.Native
{ {
Init(factory.CreatePopup(e), factory.CreateScreens()); Init(factory.CreatePopup(e), factory.CreateScreens());
} }
PopupPositioner = new ManagedPopupPositioner(new ManagedPopupPositionerPopupImplHelper(parent, MoveResize)); PopupPositioner = new ManagedPopupPositioner(new OsxManagedPopupPositionerPopupImplHelper(parent, MoveResize));
} }
private void MoveResize(PixelPoint position, Size size, double scaling) private void MoveResize(PixelPoint position, Size size, double scaling)

1
src/Avalonia.Native/ScreenImpl.cs

@ -31,6 +31,7 @@ namespace Avalonia.Native
var screen = _native.GetScreen(i); var screen = _native.GetScreen(i);
result[i] = new Screen( result[i] = new Screen(
screen.PixelDensity,
screen.Bounds.ToAvaloniaPixelRect(), screen.Bounds.ToAvaloniaPixelRect(),
screen.WorkingArea.ToAvaloniaPixelRect(), screen.WorkingArea.ToAvaloniaPixelRect(),
screen.Primary); screen.Primary);

9
src/Avalonia.Native/WindowImplBase.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Platform.Surfaces; using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Input; using Avalonia.Input;
@ -48,6 +49,11 @@ namespace Avalonia.Native
Screen = new ScreenImpl(screens); Screen = new ScreenImpl(screens);
_savedLogicalSize = ClientSize; _savedLogicalSize = ClientSize;
_savedScaling = Scaling; _savedScaling = Scaling;
var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity)
.FirstOrDefault(m => m.Bounds.Contains(Position));
Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d));
} }
public Size ClientSize public Size ClientSize
@ -300,7 +306,8 @@ namespace Avalonia.Native
_native.BeginMoveDrag(); _native.BeginMoveDrag();
} }
public Size MaxClientSize => _native.GetMaxClientSize().ToAvaloniaSize(); public Size MaxClientSize => Screen.AllScreens.Select(s => s.Bounds.Size.ToSize(s.PixelDensity))
.OrderByDescending(x => x.Width + x.Height).FirstOrDefault();
public void SetTopmost(bool value) public void SetTopmost(bool value)
{ {

4
src/Avalonia.Themes.Default/ProgressBar.xaml

@ -7,9 +7,7 @@
<Border Background="{TemplateBinding Background}" <Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"> BorderThickness="{TemplateBinding BorderThickness}">
<Border Name="PART_Indicator" <Border Name="PART_Indicator" Background="{TemplateBinding Foreground}"/>
BorderThickness="1"
Background="{TemplateBinding Foreground}"/>
</Border> </Border>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

2
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -540,7 +540,7 @@ namespace Avalonia.Rendering
foreach (var visual in _recalculateChildren) foreach (var visual in _recalculateChildren)
{ {
var node = scene.FindNode(visual); var node = scene.FindNode(visual);
((VisualNode)node)?.SortChildren(scene); ((VisualNode)node)?.UpdateChildren(scene);
} }
_recalculateChildren.Clear(); _recalculateChildren.Clear();

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

@ -174,12 +174,12 @@ namespace Avalonia.Rendering.SceneGraph
/// <summary> /// <summary>
/// Sorts the <see cref="Children"/> collection according to the order of the visual's /// Sorts the <see cref="Children"/> collection according to the order of the visual's
/// children and their z-index. /// children and their z-index and removes controls that are no longer children.
/// </summary> /// </summary>
/// <param name="scene">The scene that the node is a part of.</param> /// <param name="scene">The scene that the node is a part of.</param>
public void SortChildren(Scene scene) public void UpdateChildren(Scene scene)
{ {
if (_children == null || _children.Count <= 1) if (_children == null || _children.Count == 0)
{ {
return; return;
} }
@ -193,9 +193,12 @@ namespace Avalonia.Rendering.SceneGraph
keys.Add(((long)zIndex << 32) + i); keys.Add(((long)zIndex << 32) + i);
} }
var toRemove = _children.ToList();
keys.Sort(); keys.Sort();
_children.Clear(); _children.Clear();
foreach (var i in keys) foreach (var i in keys)
{ {
var child = Visual.VisualChildren[(int)(i & 0xffffffff)]; var child = Visual.VisualChildren[(int)(i & 0xffffffff)];
@ -204,8 +207,14 @@ namespace Avalonia.Rendering.SceneGraph
if (node != null) if (node != null)
{ {
_children.Add(node); _children.Add(node);
toRemove.Remove(node);
} }
} }
foreach (var node in toRemove)
{
scene.Remove(node);
}
} }
/// <summary> /// <summary>

2
src/Avalonia.X11/X11Screens.cs

@ -157,7 +157,7 @@ namespace Avalonia.X11
public int ScreenCount => _impl.Screens.Length; public int ScreenCount => _impl.Screens.Length;
public IReadOnlyList<Screen> AllScreens => public IReadOnlyList<Screen> AllScreens =>
_impl.Screens.Select(s => new Screen(s.Bounds, s.WorkingArea, s.Primary)).ToArray(); _impl.Screens.Select(s => new Screen(s.PixelDensity, s.Bounds, s.WorkingArea, s.Primary)).ToArray();
} }
interface IX11Screens interface IX11Screens

16
src/Avalonia.X11/X11Window.cs

@ -98,14 +98,26 @@ namespace Avalonia.X11
valueMask |= SetWindowValuemask.ColorMap; valueMask |= SetWindowValuemask.ColorMap;
} }
_handle = XCreateWindow(_x11.Display, _x11.RootWindow, 10, 10, 300, 200, 0, int defaultWidth = 300, defaultHeight = 200;
if (!_popup)
{
var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity)
.FirstOrDefault(m => m.Bounds.Contains(Position));
// Emulate Window 7+'s default window size behavior.
defaultWidth = (int)(monitor.WorkingArea.Width * 0.75d);
defaultHeight = (int)(monitor.WorkingArea.Height * 0.7d);
}
_handle = XCreateWindow(_x11.Display, _x11.RootWindow, 10, 10, defaultWidth, defaultHeight, 0,
depth, depth,
(int)CreateWindowArgs.InputOutput, (int)CreateWindowArgs.InputOutput,
visual, visual,
new UIntPtr((uint)valueMask), ref attr); new UIntPtr((uint)valueMask), ref attr);
if (_useRenderWindow) if (_useRenderWindow)
_renderHandle = XCreateWindow(_x11.Display, _handle, 0, 0, 300, 200, 0, depth, _renderHandle = XCreateWindow(_x11.Display, _handle, 0, 0, defaultWidth, defaultHeight, 0, depth,
(int)CreateWindowArgs.InputOutput, (int)CreateWindowArgs.InputOutput,
visual, visual,
new UIntPtr((uint)(SetWindowValuemask.BorderPixel | SetWindowValuemask.BitGravity | new UIntPtr((uint)(SetWindowValuemask.BorderPixel | SetWindowValuemask.BitGravity |

1
src/Shared/PlatformSupport/AssetLoader.cs

@ -242,6 +242,7 @@ namespace Avalonia.Shared.PlatformSupport
throw new InvalidOperationException( throw new InvalidOperationException(
$"Assembly {name} needs to be referenced and explicitly loaded before loading resources"); $"Assembly {name} needs to be referenced and explicitly loaded before loading resources");
#else #else
name = Uri.UnescapeDataString(name);
AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name)); AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name));
#endif #endif
} }

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

@ -30,6 +30,8 @@ namespace Avalonia.Win32
MONITORINFO monitorInfo = MONITORINFO.Create(); 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 _);
RECT bounds = monitorInfo.rcMonitor; RECT bounds = monitorInfo.rcMonitor;
RECT workingArea = monitorInfo.rcWork; RECT workingArea = monitorInfo.rcWork;
PixelRect avaloniaBounds = new PixelRect(bounds.left, bounds.top, bounds.right - bounds.left, PixelRect avaloniaBounds = new PixelRect(bounds.left, bounds.top, bounds.right - bounds.left,
@ -38,7 +40,7 @@ namespace Avalonia.Win32
new PixelRect(workingArea.left, workingArea.top, workingArea.right - workingArea.left, new PixelRect(workingArea.left, workingArea.top, workingArea.right - workingArea.left,
workingArea.bottom - workingArea.top); workingArea.bottom - workingArea.top);
screens[index] = screens[index] =
new WinScreen(avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1, new WinScreen((double)x / 96.0d, avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1,
monitor); monitor);
index++; index++;
} }

2
src/Windows/Avalonia.Win32/WinScreen.cs

@ -7,7 +7,7 @@ namespace Avalonia.Win32
{ {
private readonly IntPtr _hMonitor; private readonly IntPtr _hMonitor;
public WinScreen(PixelRect bounds, PixelRect workingArea, bool primary, IntPtr hMonitor) : base(bounds, workingArea, primary) public WinScreen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool primary, IntPtr hMonitor) : base(pixelDensity, bounds, workingArea, primary)
{ {
this._hMonitor = hMonitor; this._hMonitor = hMonitor;
} }

2
tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs

@ -198,7 +198,7 @@ namespace Avalonia.Controls.UnitTests
var screen = new PixelRect(new PixelPoint(), new PixelSize(100, 100)); var screen = new PixelRect(new PixelPoint(), new PixelSize(100, 100));
var screenImpl = new Mock<IScreenImpl>(); var screenImpl = new Mock<IScreenImpl>();
screenImpl.Setup(x => x.ScreenCount).Returns(1); screenImpl.Setup(x => x.ScreenCount).Returns(1);
screenImpl.Setup(X => X.AllScreens).Returns( new[] { new Screen(screen, screen, true) }); screenImpl.Setup(X => X.AllScreens).Returns( new[] { new Screen(1, screen, screen, true) });
popupImpl = MockWindowingPlatform.CreatePopupMock(); popupImpl = MockWindowingPlatform.CreatePopupMock();
popupImpl.SetupGet(x => x.Scaling).Returns(1); popupImpl.SetupGet(x => x.Scaling).Returns(1);

4
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@ -271,8 +271,8 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen() public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen()
{ {
var screen1 = new Mock<Screen>(new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 1040)), true); var screen1 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1920, 1080)), new PixelRect(new PixelSize(1920, 1040)), true);
var screen2 = new Mock<Screen>(new PixelRect(new PixelSize(1366, 768)), new PixelRect(new PixelSize(1366, 728)), false); var screen2 = new Mock<Screen>(1.0, new PixelRect(new PixelSize(1366, 768)), new PixelRect(new PixelSize(1366, 728)), false);
var screens = new Mock<IScreenImpl>(); var screens = new Mock<IScreenImpl>();
screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object }); screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object });

50
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

@ -270,6 +270,56 @@ namespace Avalonia.Visuals.UnitTests.Rendering
Assert.Same(stackNode.Children[1].Visual, canvas1); Assert.Same(stackNode.Children[1].Visual, canvas1);
} }
[Fact]
public void Should_Update_VisualNodes_When_Child_Moved_To_New_Parent()
{
var dispatcher = new ImmediateDispatcher();
var loop = new Mock<IRenderLoop>();
Decorator moveFrom;
Decorator moveTo;
Canvas moveMe;
var root = new TestRoot
{
Child = new StackPanel
{
Children =
{
(moveFrom = new Decorator
{
Child = moveMe = new Canvas(),
}),
(moveTo = new Decorator()),
}
}
};
var sceneBuilder = new SceneBuilder();
var target = new DeferredRenderer(
root,
loop.Object,
sceneBuilder: sceneBuilder,
dispatcher: dispatcher);
root.Renderer = target;
target.Start();
RunFrame(target);
moveFrom.Child = null;
moveTo.Child = moveMe;
RunFrame(target);
var scene = target.UnitTestScene();
var moveFromNode = (VisualNode)scene.FindNode(moveFrom);
var moveToNode = (VisualNode)scene.FindNode(moveTo);
Assert.Empty(moveFromNode.Children);
Assert.Equal(1, moveToNode.Children.Count);
Assert.Same(moveMe, moveToNode.Children[0].Visual);
}
[Fact] [Fact]
public void Should_Push_Opacity_For_Controls_With_Less_Than_1_Opacity() public void Should_Push_Opacity_For_Controls_With_Less_Than_1_Opacity()
{ {

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

@ -475,6 +475,64 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
} }
} }
[Fact]
public void Should_Update_When_Control_Moved()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
Decorator moveFrom;
Decorator moveTo;
Canvas moveMe;
var tree = new TestRoot
{
Width = 100,
Height = 100,
Child = new StackPanel
{
Children =
{
(moveFrom = new Decorator
{
Child = moveMe = new Canvas(),
}),
(moveTo = new Decorator()),
}
}
};
tree.Measure(Size.Infinity);
tree.Arrange(new Rect(tree.DesiredSize));
var scene = new Scene(tree);
var sceneBuilder = new SceneBuilder();
sceneBuilder.UpdateAll(scene);
var moveFromNode = (VisualNode)scene.FindNode(moveFrom);
var moveToNode = (VisualNode)scene.FindNode(moveTo);
Assert.Equal(1, moveFromNode.Children.Count);
Assert.Same(moveMe, moveFromNode.Children[0].Visual);
Assert.Empty(moveToNode.Children);
moveFrom.Child = null;
moveTo.Child = moveMe;
scene = scene.CloneScene();
moveFromNode = (VisualNode)scene.FindNode(moveFrom);
moveToNode = (VisualNode)scene.FindNode(moveTo);
moveFromNode.UpdateChildren(scene);
moveToNode.UpdateChildren(scene);
sceneBuilder.Update(scene, moveFrom);
sceneBuilder.Update(scene, moveTo);
sceneBuilder.Update(scene, moveMe);
Assert.Empty(moveFromNode.Children);
Assert.Equal(1, moveToNode.Children.Count);
Assert.Same(moveMe, moveToNode.Children[0].Visual);
}
}
[Fact] [Fact]
public void Should_Update_When_Control_Made_Invisible() public void Should_Update_When_Control_Made_Invisible()
{ {

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

@ -99,7 +99,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
var node = new VisualNode(Mock.Of<IVisual>(), null); var node = new VisualNode(Mock.Of<IVisual>(), null);
var scene = new Scene(Mock.Of<IVisual>()); var scene = new Scene(Mock.Of<IVisual>());
node.SortChildren(scene); node.UpdateChildren(scene);
} }
} }
} }

Loading…
Cancel
Save