From c1dd44ead4cf42d13bb36b4ef74b1caa52a4c35e Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Sun, 21 Oct 2018 23:48:43 +0300 Subject: [PATCH 01/59] unit test for issue #2000 button with render transform don't trigger click --- .../ButtonTests.cs | 165 +++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs index d218960726..9c9d09d4f8 100644 --- a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs @@ -1,7 +1,10 @@ using System; using System.Windows.Input; using Avalonia.Data; -using Avalonia.Markup.Data; +using Avalonia.Input; +using Avalonia.Media; +using Avalonia.VisualTree; +using Moq; using Xunit; namespace Avalonia.Controls.UnitTests @@ -92,6 +95,164 @@ namespace Avalonia.Controls.UnitTests Assert.False(target.IsEnabled); } + [Fact] + public void Button_Is_Raising_Click() + { + var mouse = Mock.Of(); + IInputElement captured = null; + Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(50, 50)); + Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); + Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); + + var target = new TestButton() { Bounds = new Rect(0, 0, 100, 100) }; + + bool clicked = false; + + target.Click += (s, e) => clicked = true; + + RaisePointerEnter(target, mouse); + RaisePointerMove(target, mouse); + RaisePointerPressed(target, mouse, 1, MouseButton.Left); + + Assert.Equal(captured, target); + + RaisePointerReleased(target, mouse, MouseButton.Left); + + Assert.Equal(captured, null); + + Assert.True(clicked); + } + + [Fact] + public void Button_Is_Not_Raising_Click_When_PointerReleased_Outside() + { + var mouse = Mock.Of(); + IInputElement captured = null; + Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(200, 50)); + Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); + Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); + + var target = new TestButton() { Bounds = new Rect(0, 0, 100, 100) }; + + bool clicked = false; + + target.Click += (s, e) => clicked = true; + + RaisePointerEnter(target, mouse); + RaisePointerMove(target, mouse); + RaisePointerPressed(target, mouse, 1, MouseButton.Left); + RaisePointerLeave(target, mouse); + + Assert.Equal(captured, target); + + RaisePointerReleased(target, mouse, MouseButton.Left); + + Assert.Equal(captured, null); + + Assert.False(clicked); + } + + [Fact] + public void Button_With_RenderTransform_Is_Raising_Click() + { + var mouse = Mock.Of(); + IInputElement captured = null; + Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(150, 50)); + Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); + Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); + + var target = new TestButton() + { + Bounds = new Rect(0, 0, 100, 100), + RenderTransform = new TranslateTransform { X = 100, Y = 0 } + }; + + //actual bounds of button should be 100,0,100,100 x -> translated 100 pixels + //so mouse with x=150 coordinates should trigger click + //button shouldn't count on bounds to calculate pointer is in the over or not, but + //on avalonia event system, as renderer hit test will properly calculate whether to send + //mouse over events to button based on rendered bounds + //note: button also may have not rectangular shape and only renderer hit testing is reliable + + bool clicked = false; + + target.Click += (s, e) => clicked = true; + + RaisePointerEnter(target, mouse); + RaisePointerMove(target, mouse); + RaisePointerPressed(target, mouse, 1, MouseButton.Left); + + Assert.Equal(captured, target); + + RaisePointerReleased(target, mouse, MouseButton.Left); + + Assert.Equal(captured, null); + + Assert.True(clicked); + } + + private class TestButton : Button + { + public new Rect Bounds + { + get => base.Bounds; + set => base.Bounds = value; + } + } + + private void RaisePointerPressed(Button button, IMouseDevice device, int clickCount, MouseButton mouseButton) + { + button.RaiseEvent(new PointerPressedEventArgs + { + RoutedEvent = InputElement.PointerPressedEvent, + Source = button, + MouseButton = mouseButton, + ClickCount = clickCount, + Device = device, + }); + } + + private void RaisePointerReleased(Button button, IMouseDevice device, MouseButton mouseButton) + { + button.RaiseEvent(new PointerReleasedEventArgs + { + RoutedEvent = InputElement.PointerReleasedEvent, + Source = button, + MouseButton = mouseButton, + Device = device, + }); + } + + private void RaisePointerEnter(Button button, IMouseDevice device) + { + button.RaiseEvent(new PointerEventArgs + { + RoutedEvent = InputElement.PointerEnterEvent, + Source = button, + Device = device, + }); + } + + private void RaisePointerLeave(Button button, IMouseDevice device) + { + button.RaiseEvent(new PointerEventArgs + { + RoutedEvent = InputElement.PointerLeaveEvent, + Source = button, + Device = device, + }); + } + + private void RaisePointerMove(Button button, IMouseDevice device) + { + button.RaiseEvent(new PointerEventArgs + { + RoutedEvent = InputElement.PointerMovedEvent, + Source = button, + Device = device, + }); + } + private class TestCommand : ICommand { private bool _enabled; @@ -123,4 +284,4 @@ namespace Avalonia.Controls.UnitTests } } } -} \ No newline at end of file +} From e1874b4a4c442f0cda18ffe9e02d1304d783913b Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 23 Oct 2018 01:13:04 +0300 Subject: [PATCH 02/59] fix for issue #2000 button with rendertransform don't fire click --- src/Avalonia.Controls/Button.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 24b2af7996..9c4c33f549 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -251,7 +251,9 @@ namespace Avalonia.Controls IsPressed = false; e.Handled = true; - if (ClickMode == ClickMode.Release && new Rect(Bounds.Size).Contains(e.GetPosition(this))) + //only renderer (hittesting) know better whether pointer is over the bounds of the button + if (ClickMode == ClickMode.Release && + (IsPointerOver || new Rect(Bounds.Size).Contains(e.GetPosition(this)))) { OnClick(); } From a600fb52ae17e05ae97f311396d0ad715fb08662 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Sun, 21 Oct 2018 18:42:35 +0300 Subject: [PATCH 03/59] unit test for invalidate on immediate renderer when renderedtransfom is used, issue #1998 --- .../Rendering/ImmediateRendererTests.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs new file mode 100644 index 0000000000..1fff36f8ff --- /dev/null +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Avalonia.Media; +using Avalonia.Rendering; +using Avalonia.VisualTree; +using Moq; +using Xunit; + +namespace Avalonia.Visuals.UnitTests.Rendering +{ + public class ImmediateRendererTests + { + [Fact] + public void AddDirty_Call_RenderRoot_Invalidate() + { + var visual = new Mock(); + var child = new Mock(); + var renderRoot = visual.As(); + + visual.As().Setup(v => v.Bounds).Returns(new Rect(0, 0, 400, 400)); + + child.As().Setup(v => v.Bounds).Returns(new Rect(10, 10, 100, 100)); + child.As().Setup(v => v.VisualParent).Returns(visual.Object); + child.As().Setup(v => v.RenderTransform).Returns(default(Transform)); + child.As().Setup(v => v.RenderTransformOrigin).Returns(new RelativePoint(0.5, 0.5, RelativeUnit.Relative)); + child.As().Setup(v => v.TransformToVisual(It.IsAny())).CallBase(); + + var target = new ImmediateRenderer(visual.Object); + + target.AddDirty(child.Object); + + renderRoot.Verify(v => v.Invalidate(new Rect(10, 10, 100, 100))); + } + + + [Fact] + public void AddDirty_With_RenderTransform_Call_RenderRoot_Invalidate() + { + var visual = new Mock(); + var child = new Mock(); + var renderRoot = visual.As(); + + visual.As().Setup(v => v.Bounds).Returns(new Rect(0, 0, 400, 400)); + + child.As().Setup(v => v.Bounds).Returns(new Rect(100, 100, 100, 100)); + child.As().Setup(v => v.VisualParent).Returns(visual.Object); + child.As().Setup(v => v.RenderTransform).Returns(new ScaleTransform() { ScaleX = 2, ScaleY = 2 }); + child.As().Setup(v => v.RenderTransformOrigin).Returns(new RelativePoint(0.5, 0.5, RelativeUnit.Relative)); + child.As().Setup(v => v.TransformToVisual(It.IsAny())).CallBase(); + + var target = new ImmediateRenderer(visual.Object); + + target.AddDirty(child.Object); + + renderRoot.Verify(v => v.Invalidate(new Rect(50, 50, 200, 200))); + } + + + public class TestVisual : Visual + { + public new Rect Bounds + { + get => base.Bounds; + set => base.Bounds = value; + } + } + } +} From 7fd6975658b6fe82deb7f461174480d4b6642753 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 23 Oct 2018 01:19:16 +0300 Subject: [PATCH 04/59] fix ImmediateRenderer invalidation for controls with RenderTransform issue #1998 --- .../Rendering/ImmediateRenderer.cs | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs index d373e7ef2a..96512b41a1 100644 --- a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs @@ -115,12 +115,45 @@ namespace Avalonia.Rendering } } + private static Matrix? TransformToVisual(IVisual visual, IVisual root) + { + var result = Matrix.Identity; + + while (visual != root) + { + if (visual.RenderTransform?.Value != null) + { + var origin = visual.RenderTransformOrigin.ToPixels(visual.Bounds.Size); + var offset = Matrix.CreateTranslation(origin); + var renderTransform = (-offset) * visual.RenderTransform.Value * (offset); + + result *= renderTransform; + } + + var topLeft = visual.Bounds.TopLeft; + + if (topLeft != default) + { + result *= Matrix.CreateTranslation(topLeft); + } + + visual = visual.VisualParent; + + if (visual == null) + { + return null; + } + } + + return result; + } + /// public void AddDirty(IVisual visual) { if (visual.Bounds != Rect.Empty) { - var m = visual.TransformToVisual(_root); + var m = TransformToVisual(visual, _root); if (m.HasValue) { @@ -191,7 +224,7 @@ namespace Avalonia.Rendering } } - static IEnumerable HitTest( + private static IEnumerable HitTest( IVisual visual, Point p, Func filter) From 5ce71be598691be6b34caaee56076096f1bded52 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 23 Oct 2018 14:00:30 +0300 Subject: [PATCH 05/59] another failing unit test for invalidate on immediate renderer when renderedtransfom is used, issue #1998 --- .../Rendering/ImmediateRendererTests.cs | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs index 1fff36f8ff..41e1691f28 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs @@ -1,7 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; +using Avalonia.Collections; using Avalonia.Media; +using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.VisualTree; using Moq; @@ -33,7 +33,6 @@ namespace Avalonia.Visuals.UnitTests.Rendering renderRoot.Verify(v => v.Invalidate(new Rect(10, 10, 100, 100))); } - [Fact] public void AddDirty_With_RenderTransform_Call_RenderRoot_Invalidate() { @@ -56,6 +55,51 @@ namespace Avalonia.Visuals.UnitTests.Rendering renderRoot.Verify(v => v.Invalidate(new Rect(50, 50, 200, 200))); } + [Fact] + public void AddDirty_For_Child_Moved_Should_Invalidate_Previous_Bounds() + { + var visual = new Mock(); + var child = new Mock(); + var renderRoot = visual.As(); + var renderTarget = visual.As(); + + renderRoot.Setup(r => r.CreateRenderTarget()).Returns(renderTarget.Object); + renderTarget.Setup(r => r.CreateDrawingContext(It.IsAny())).Returns(Mock.Of()); + + visual.As().Setup(v => v.Bounds).Returns(new Rect(0, 0, 400, 400)); + visual.As().Setup(v => v.VisualChildren).Returns(new AvaloniaList() { child.As().Object }); + + Rect childBounds = new Rect(0, 0, 100, 100); + child.As().Setup(v => v.Bounds).Returns(() => childBounds); + child.As().Setup(v => v.VisualParent).Returns(visual.Object); + child.As().Setup(v => v.TransformToVisual(It.IsAny())).CallBase(); + child.As().Setup(v => v.VisualChildren).Returns(new AvaloniaList()); + + var invalidationCalls = new List(); + + renderRoot.Setup(v => v.Invalidate(It.IsAny())).Callback(v => invalidationCalls.Add(v)); + + var target = new ImmediateRenderer(visual.Object); + + target.AddDirty(child.Object); + + Assert.Equal(new Rect(0, 0, 100, 100), invalidationCalls[0]); + + target.Paint(new Rect(0, 0, 100, 100)); + + //move child 100 pixels bottom/right + childBounds = new Rect(100, 100, 100, 100); + + //renderer should invalidate old child bounds with new one + //as on old area there can be artifacts + target.AddDirty(child.Object); + + //invalidate first old position + Assert.Equal(new Rect(0, 0, 100, 100), invalidationCalls[1]); + + //then new position + Assert.Equal(new Rect(100, 100, 100, 100), invalidationCalls[2]); + } public class TestVisual : Visual { From 03384d3b5efea383f435e276efea055d83627680 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 23 Oct 2018 14:05:53 +0300 Subject: [PATCH 06/59] fix ImmediateRenderer invalidation for controls moved with RenderTransform issue #1998 --- src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs index 96512b41a1..e5e3533bf6 100644 --- a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs @@ -23,6 +23,7 @@ namespace Avalonia.Rendering private readonly IVisual _root; private readonly IRenderRoot _renderRoot; private IRenderTarget _renderTarget; + private Rect _lastPaintBounds; /// /// Initializes a new instance of the class. @@ -45,6 +46,8 @@ namespace Avalonia.Rendering /// public void Paint(Rect rect) { + _lastPaintBounds = rect; + if (_renderTarget == null) { _renderTarget = ((IRenderRoot)_root).CreateRenderTarget(); @@ -158,6 +161,13 @@ namespace Avalonia.Rendering if (m.HasValue) { var bounds = new Rect(visual.Bounds.Size).TransformToAABB(m.Value); + + if (_lastPaintBounds != default) + { + _renderRoot?.Invalidate(_lastPaintBounds); + _lastPaintBounds = default; + } + _renderRoot?.Invalidate(bounds); } } From 922917b29937ca0cc07e4a2d7d62c3bc5e0f8503 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 23 Oct 2018 14:12:00 +0300 Subject: [PATCH 07/59] fix pr nits --- src/Avalonia.Controls/Button.cs | 1 - tests/Avalonia.Controls.UnitTests/ButtonTests.cs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 9c4c33f549..0e8a765e57 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -251,7 +251,6 @@ namespace Avalonia.Controls IsPressed = false; e.Handled = true; - //only renderer (hittesting) know better whether pointer is over the bounds of the button if (ClickMode == ClickMode.Release && (IsPointerOver || new Rect(Bounds.Size).Contains(e.GetPosition(this)))) { diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs index 9c9d09d4f8..afc53f2fa9 100644 --- a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs @@ -96,7 +96,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Button_Is_Raising_Click() + public void Button_Raises_Click() { var mouse = Mock.Of(); IInputElement captured = null; @@ -124,7 +124,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Button_Is_Not_Raising_Click_When_PointerReleased_Outside() + public void Button_Does_Not_Raise_Click_When_PointerReleased_Outside() { var mouse = Mock.Of(); IInputElement captured = null; @@ -153,7 +153,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Button_With_RenderTransform_Is_Raising_Click() + public void Button_With_RenderTransform_Raises_Click() { var mouse = Mock.Of(); IInputElement captured = null; From ef158e3ec36bdd32bec03a9aa36b8ca88b48f7be Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 26 Oct 2018 10:59:49 +0300 Subject: [PATCH 08/59] hittest when button is pressed --- src/Avalonia.Controls/Button.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 0e8a765e57..dc65df2584 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.Linq; using System.Windows.Input; using Avalonia.Data; using Avalonia.Input; @@ -251,8 +252,9 @@ namespace Avalonia.Controls IsPressed = false; e.Handled = true; - if (ClickMode == ClickMode.Release && - (IsPointerOver || new Rect(Bounds.Size).Contains(e.GetPosition(this)))) + var hittest = VisualRoot?.Renderer?.HitTest(e.GetPosition(VisualRoot), VisualRoot, null); + + if (ClickMode == ClickMode.Release && hittest?.Any(v => v == this) == true) { OnClick(); } @@ -262,9 +264,9 @@ namespace Avalonia.Controls protected override void UpdateDataValidation(AvaloniaProperty property, BindingNotification status) { base.UpdateDataValidation(property, status); - if(property == CommandProperty) + if (property == CommandProperty) { - if(status?.ErrorType == BindingErrorType.Error) + if (status?.ErrorType == BindingErrorType.Error) { IsEnabled = false; } From 87437b82327b63bfffa58c6a860747d07c045313 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 26 Oct 2018 11:29:00 +0300 Subject: [PATCH 09/59] update button unit tests --- .../ButtonTests.cs | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs index afc53f2fa9..c318229700 100644 --- a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs @@ -3,6 +3,8 @@ using System.Windows.Input; using Avalonia.Data; using Avalonia.Input; using Avalonia.Media; +using Avalonia.Platform; +using Avalonia.Rendering; using Avalonia.VisualTree; using Moq; using Xunit; @@ -99,12 +101,20 @@ namespace Avalonia.Controls.UnitTests public void Button_Raises_Click() { var mouse = Mock.Of(); + var renderer = Mock.Of(); IInputElement captured = null; Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(50, 50)); Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); + Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), null)) + .Returns>((p, r, f) => + r.Bounds.Contains(p) ? new IVisual[] { r } : new IVisual[0]); - var target = new TestButton() { Bounds = new Rect(0, 0, 100, 100) }; + var target = new TestButton() + { + Bounds = new Rect(0, 0, 100, 100), + Renderer = renderer + }; bool clicked = false; @@ -127,12 +137,20 @@ namespace Avalonia.Controls.UnitTests public void Button_Does_Not_Raise_Click_When_PointerReleased_Outside() { var mouse = Mock.Of(); + var renderer = Mock.Of(); IInputElement captured = null; Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(200, 50)); Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); + Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), null)) + .Returns>((p, r, f) => + r.Bounds.Contains(p) ? new IVisual[] { r } : new IVisual[0]); - var target = new TestButton() { Bounds = new Rect(0, 0, 100, 100) }; + var target = new TestButton() + { + Bounds = new Rect(0, 0, 100, 100), + Renderer = renderer + }; bool clicked = false; @@ -156,15 +174,21 @@ namespace Avalonia.Controls.UnitTests public void Button_With_RenderTransform_Raises_Click() { var mouse = Mock.Of(); + var renderer = Mock.Of(); IInputElement captured = null; Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(150, 50)); Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); + Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), null)) + .Returns>((p, r, f) => + r.Bounds.Contains(p.Transform(r.RenderTransform.Value.Invert())) ? + new IVisual[] { r } : new IVisual[0]); var target = new TestButton() { Bounds = new Rect(0, 0, 100, 100), - RenderTransform = new TranslateTransform { X = 100, Y = 0 } + RenderTransform = new TranslateTransform { X = 100, Y = 0 }, + Renderer = renderer }; //actual bounds of button should be 100,0,100,100 x -> translated 100 pixels @@ -191,13 +215,27 @@ namespace Avalonia.Controls.UnitTests Assert.True(clicked); } - private class TestButton : Button + private class TestButton : Button, IRenderRoot { public new Rect Bounds { get => base.Bounds; set => base.Bounds = value; } + + public Size ClientSize => throw new NotImplementedException(); + + public IRenderer Renderer { get; set; } + + public double RenderScaling => throw new NotImplementedException(); + + public IRenderTarget CreateRenderTarget() => throw new NotImplementedException(); + + public void Invalidate(Rect rect) => throw new NotImplementedException(); + + public Point PointToClient(Point point) => throw new NotImplementedException(); + + public Point PointToScreen(Point point) => throw new NotImplementedException(); } private void RaisePointerPressed(Button button, IMouseDevice device, int clickCount, MouseButton mouseButton) From 08d552de108c613d3f0bd745ff48ba80aa89a1aa Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 26 Oct 2018 16:11:38 +0300 Subject: [PATCH 10/59] fix button click for deferedrenderer --- src/Avalonia.Controls/Button.cs | 6 ++++-- tests/Avalonia.Controls.UnitTests/ButtonTests.cs | 11 ++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index dc65df2584..2d80af8e4a 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -7,6 +7,7 @@ using System.Windows.Input; using Avalonia.Data; using Avalonia.Input; using Avalonia.Interactivity; +using Avalonia.VisualTree; namespace Avalonia.Controls { @@ -252,9 +253,10 @@ namespace Avalonia.Controls IsPressed = false; e.Handled = true; - var hittest = VisualRoot?.Renderer?.HitTest(e.GetPosition(VisualRoot), VisualRoot, null); + var hittest = this.GetVisualsAt(e.GetPosition(this)); - if (ClickMode == ClickMode.Release && hittest?.Any(v => v == this) == true) + if (ClickMode == ClickMode.Release && + hittest.Any(c => c == this || (c as IStyledElement)?.TemplatedParent == this) == true) { OnClick(); } diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs index c318229700..76f2898700 100644 --- a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs @@ -106,7 +106,7 @@ namespace Avalonia.Controls.UnitTests Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(50, 50)); Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); - Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), null)) + Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), It.IsAny>())) .Returns>((p, r, f) => r.Bounds.Contains(p) ? new IVisual[] { r } : new IVisual[0]); @@ -142,7 +142,7 @@ namespace Avalonia.Controls.UnitTests Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(200, 50)); Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); - Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), null)) + Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), It.IsAny>())) .Returns>((p, r, f) => r.Bounds.Contains(p) ? new IVisual[] { r } : new IVisual[0]); @@ -179,7 +179,7 @@ namespace Avalonia.Controls.UnitTests Mock.Get(mouse).Setup(m => m.GetPosition(It.IsAny())).Returns(new Point(150, 50)); Mock.Get(mouse).Setup(m => m.Capture(It.IsAny())).Callback(v => captured = v); Mock.Get(mouse).Setup(m => m.Captured).Returns(() => captured); - Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), null)) + Mock.Get(renderer).Setup(r => r.HitTest(It.IsAny(), It.IsAny(), It.IsAny>())) .Returns>((p, r, f) => r.Bounds.Contains(p.Transform(r.RenderTransform.Value.Invert())) ? new IVisual[] { r } : new IVisual[0]); @@ -217,6 +217,11 @@ namespace Avalonia.Controls.UnitTests private class TestButton : Button, IRenderRoot { + public TestButton() + { + IsVisible = true; + } + public new Rect Bounds { get => base.Bounds; From 8461bfc6887cbfba8e13064d2f530b7d796b100b Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Mon, 29 Oct 2018 17:21:16 +0200 Subject: [PATCH 11/59] add tests for transform to visual --- .../Avalonia.Visuals.UnitTests/VisualTests.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/Avalonia.Visuals.UnitTests/VisualTests.cs b/tests/Avalonia.Visuals.UnitTests/VisualTests.cs index b62bf5858d..0414ac4c74 100644 --- a/tests/Avalonia.Visuals.UnitTests/VisualTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/VisualTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using Avalonia.Controls; +using Avalonia.Media; using Avalonia.Rendering; using Avalonia.UnitTests; using Avalonia.VisualTree; @@ -192,5 +193,48 @@ namespace Avalonia.Visuals.UnitTests Assert.Throws(() => root2.Child = child); Assert.Empty(root2.GetVisualChildren()); } + + [Fact] + public void TransformToVisual_Should_Work() + { + var child = new Decorator { Width = 100, Height = 100 }; + var root = new TestRoot() { Child = child, Width = 400, Height = 400 }; + + root.Measure(Size.Infinity); + root.Arrange(new Rect(new Point(), root.DesiredSize)); + + var tr = child.TransformToVisual(root); + + Assert.NotNull(tr); + + var point = root.Bounds.TopLeft * tr; + + //child is centered (400 - 100)/2 + Assert.Equal(new Point(150, 150), point); + } + + [Fact] + public void TransformToVisual_With_RenderTransform_Should_Work() + { + var child = new Decorator + { + Width = 100, + Height = 100, + RenderTransform = new ScaleTransform() { ScaleX = 2, ScaleY = 2 } + }; + var root = new TestRoot() { Child = child, Width = 400, Height = 400 }; + + root.Measure(Size.Infinity); + root.Arrange(new Rect(new Point(), root.DesiredSize)); + + var tr = child.TransformToVisual(root); + + Assert.NotNull(tr); + + var point = root.Bounds.TopLeft * tr; + + //child is centered (400 - 100*2 scale)/2 + Assert.Equal(new Point(100, 100), point); + } } } From 85c786e4e993488e47e58a2f37feb2604cf80406 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Mon, 29 Oct 2018 17:23:08 +0200 Subject: [PATCH 12/59] Fir TransformToVisual and use it in ImmediateRenderer --- .../Rendering/ImmediateRenderer.cs | 35 +------------------ src/Avalonia.Visuals/Visual.cs | 23 +++++++++--- 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs index e5e3533bf6..967dd24acf 100644 --- a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs @@ -118,45 +118,12 @@ namespace Avalonia.Rendering } } - private static Matrix? TransformToVisual(IVisual visual, IVisual root) - { - var result = Matrix.Identity; - - while (visual != root) - { - if (visual.RenderTransform?.Value != null) - { - var origin = visual.RenderTransformOrigin.ToPixels(visual.Bounds.Size); - var offset = Matrix.CreateTranslation(origin); - var renderTransform = (-offset) * visual.RenderTransform.Value * (offset); - - result *= renderTransform; - } - - var topLeft = visual.Bounds.TopLeft; - - if (topLeft != default) - { - result *= Matrix.CreateTranslation(topLeft); - } - - visual = visual.VisualParent; - - if (visual == null) - { - return null; - } - } - - return result; - } - /// public void AddDirty(IVisual visual) { if (visual.Bounds != Rect.Empty) { - var m = TransformToVisual(visual, _root); + var m = visual.TransformToVisual(_root); if (m.HasValue) { diff --git a/src/Avalonia.Visuals/Visual.cs b/src/Avalonia.Visuals/Visual.cs index e5fcf1ba1d..f26c21d1b6 100644 --- a/src/Avalonia.Visuals/Visual.cs +++ b/src/Avalonia.Visuals/Visual.cs @@ -304,7 +304,7 @@ namespace Avalonia { var thisOffset = GetOffsetFrom(common, this); var thatOffset = GetOffsetFrom(common, visual); - return Matrix.CreateTranslation(-thatOffset) * Matrix.CreateTranslation(thisOffset); + return -thatOffset * thisOffset; } return null; @@ -454,13 +454,28 @@ namespace Avalonia /// The ancestor visual. /// The visual. /// The visual offset. - private static Vector GetOffsetFrom(IVisual ancestor, IVisual visual) + private static Matrix GetOffsetFrom(IVisual ancestor, IVisual visual) { - var result = new Vector(); + var result = Matrix.Identity; while (visual != ancestor) { - result = new Vector(result.X + visual.Bounds.X, result.Y + visual.Bounds.Y); + if (visual.RenderTransform?.Value != null) + { + var origin = visual.RenderTransformOrigin.ToPixels(visual.Bounds.Size); + var offset = Matrix.CreateTranslation(origin); + var renderTransform = (-offset) * visual.RenderTransform.Value * (offset); + + result *= renderTransform; + } + + var topLeft = visual.Bounds.TopLeft; + + if (topLeft != default) + { + result *= Matrix.CreateTranslation(topLeft); + } + visual = visual.VisualParent; if (visual == null) From 6a537bea115d24b3e618379c7461ae52b5f92167 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 29 Oct 2018 21:47:38 +0000 Subject: [PATCH 13/59] fix keyboard input on osx. --- .../xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme | 4 ++-- src/Avalonia.Native/AvaloniaNativePlatform.cs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme index c1cc9b4887..1a665d3ea5 100644 --- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme +++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme @@ -38,7 +38,7 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" launchStyle = "0" useCustomWorkingDirectory = "YES" - customWorkingDirectory = "$PROJECT_DIR/../../../../samples/ControlCatalog" + customWorkingDirectory = "$PROJECT_DIR/../../../../samples/ControlCatalog.NetCore" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" @@ -58,7 +58,7 @@ diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index 091a4ad285..ff410ddbe3 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -76,6 +76,7 @@ namespace Avalonia.Native .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())) .Bind().ToConstant(new GlPlatformFeature(_factory.ObtainGlFeature())) + .Bind().ToConstant(new PlatformHotkeyConfiguration(InputModifiers.Windows)) .Bind().ToConstant(opts); } From 80a95c5baee9bcf06e28617b0455d23f58a35994 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 09:41:17 +0000 Subject: [PATCH 14/59] fix call from invalid thread in previewer. --- .../Remote/Server/RemoteServerTopLevelImpl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs index 17cdbf834c..e1767fca36 100644 --- a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs +++ b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs @@ -211,10 +211,10 @@ namespace Avalonia.Controls.Remote.Server } if(obj is KeyEventMessage key) { - Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); - Dispatcher.UIThread.Post(() => { + Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); + Input?.Invoke(new RawKeyEventArgs( KeyboardDevice, 0, @@ -225,10 +225,10 @@ namespace Avalonia.Controls.Remote.Server } if(obj is TextInputEventMessage text) { - Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); - Dispatcher.UIThread.Post(() => { + Dispatcher.UIThread.RunJobs(DispatcherPriority.Input + 1); + Input?.Invoke(new RawTextInputEventArgs( KeyboardDevice, 0, From 7b4b2a0a4389c70c8576c90ccc8d5d39a3550eeb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 10:29:33 +0000 Subject: [PATCH 15/59] add previewer location as an msbuild property. --- Avalonia.sln | 1 + build/Avalonia.Designer.HostApp.props | 8 ++++++++ packages/Avalonia/Avalonia.csproj | 7 ++++++- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 build/Avalonia.Designer.HostApp.props diff --git a/Avalonia.sln b/Avalonia.sln index 7fa5f7736a..bf75c35d10 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -128,6 +128,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}" ProjectSection(SolutionItems) = preProject + build\Avalonia.Designer.HostApp.props = build\Avalonia.Designer.HostApp.props build\Base.props = build\Base.props build\Binding.props = build\Binding.props build\JetBrains.Annotations.props = build\JetBrains.Annotations.props diff --git a/build/Avalonia.Designer.HostApp.props b/build/Avalonia.Designer.HostApp.props new file mode 100644 index 0000000000..c3a9ce20a7 --- /dev/null +++ b/build/Avalonia.Designer.HostApp.props @@ -0,0 +1,8 @@ + + + $(MSBuildThisFileDirectory)\..\..\tools\netcoreapp2.0\designer\Avalonia.Designer.HostApp.dll + + + $(MSBuildThisFileDirectory)\..\..\tools\net461\designer\Avalonia.Designer.HostApp.exe + + diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj index ae209f085e..32a953ea9e 100644 --- a/packages/Avalonia/Avalonia.csproj +++ b/packages/Avalonia/Avalonia.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net461;netcoreapp2.0 @@ -27,6 +27,11 @@ false None + <_PackageFiles Include="../../build/Avalonia.Designer.HostApp.props"> + build/Avalonia.props + false + None + From 52e5f6fd23d738fb4481647965a5b14b8b8f1eac Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 12:08:55 +0000 Subject: [PATCH 16/59] suggested changes --- Avalonia.sln | 1 - {build => packages/Avalonia}/Avalonia.Designer.HostApp.props | 2 ++ packages/Avalonia/Avalonia.csproj | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename {build => packages/Avalonia}/Avalonia.Designer.HostApp.props (81%) diff --git a/Avalonia.sln b/Avalonia.sln index bf75c35d10..7fa5f7736a 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -128,7 +128,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}" ProjectSection(SolutionItems) = preProject - build\Avalonia.Designer.HostApp.props = build\Avalonia.Designer.HostApp.props build\Base.props = build\Base.props build\Binding.props = build\Binding.props build\JetBrains.Annotations.props = build\JetBrains.Annotations.props diff --git a/build/Avalonia.Designer.HostApp.props b/packages/Avalonia/Avalonia.Designer.HostApp.props similarity index 81% rename from build/Avalonia.Designer.HostApp.props rename to packages/Avalonia/Avalonia.Designer.HostApp.props index c3a9ce20a7..fd7ecc9d12 100644 --- a/build/Avalonia.Designer.HostApp.props +++ b/packages/Avalonia/Avalonia.Designer.HostApp.props @@ -1,8 +1,10 @@  $(MSBuildThisFileDirectory)\..\..\tools\netcoreapp2.0\designer\Avalonia.Designer.HostApp.dll + dotnet exec $(MSBuildThisFileDirectory)\..\..\tools\net461\designer\Avalonia.Designer.HostApp.exe + exe diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj index 32a953ea9e..61e29b8016 100644 --- a/packages/Avalonia/Avalonia.csproj +++ b/packages/Avalonia/Avalonia.csproj @@ -27,7 +27,7 @@ false None - <_PackageFiles Include="../../build/Avalonia.Designer.HostApp.props"> + <_PackageFiles Include="build/Avalonia.Designer.HostApp.props"> build/Avalonia.props false None From 93b507fc116a8a63bfb0a5d35075a1d0c20ffc85 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 12:25:49 +0000 Subject: [PATCH 17/59] rename props file. --- packages/Avalonia/Avalonia.csproj | 2 +- .../{Avalonia.Designer.HostApp.props => Avalonia.props} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/Avalonia/{Avalonia.Designer.HostApp.props => Avalonia.props} (100%) diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj index 61e29b8016..4cb2877b2f 100644 --- a/packages/Avalonia/Avalonia.csproj +++ b/packages/Avalonia/Avalonia.csproj @@ -27,7 +27,7 @@ false None - <_PackageFiles Include="build/Avalonia.Designer.HostApp.props"> + <_PackageFiles Include="build/Avalonia.props"> build/Avalonia.props false None diff --git a/packages/Avalonia/Avalonia.Designer.HostApp.props b/packages/Avalonia/Avalonia.props similarity index 100% rename from packages/Avalonia/Avalonia.Designer.HostApp.props rename to packages/Avalonia/Avalonia.props From 2eceba9e741bcea404f3633488dd7c436f4b962e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 13:34:32 +0000 Subject: [PATCH 18/59] fix location of avalonia.props. --- packages/Avalonia/Avalonia.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Avalonia/Avalonia.csproj b/packages/Avalonia/Avalonia.csproj index 4cb2877b2f..dee42fb795 100644 --- a/packages/Avalonia/Avalonia.csproj +++ b/packages/Avalonia/Avalonia.csproj @@ -27,7 +27,7 @@ false None - <_PackageFiles Include="build/Avalonia.props"> + <_PackageFiles Include="Avalonia.props"> build/Avalonia.props false None From 2daa13a11d8dcee48fce7c4de062e1985af33571 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 13:54:47 +0000 Subject: [PATCH 19/59] update build script to package releasable packages on release branches. --- parameters.cake | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/parameters.cake b/parameters.cake index 8d813accbb..8bf6ed8173 100644 --- a/parameters.cake +++ b/parameters.cake @@ -18,6 +18,7 @@ public class Parameters public bool IsPullRequest { get; private set; } public bool IsMainRepo { get; private set; } public bool IsMasterBranch { get; private set; } + public bool IsReleaseBranch { get; private set; } public bool IsTagged { get; private set; } public bool IsReleasable { get; private set; } public bool IsMyGetRelease { get; private set; } @@ -46,8 +47,9 @@ public class Parameters SkipTests = context.HasArgument("skip-tests"); // CONFIGURATION - MainRepo = "AvaloniaUI/Avalonia"; + MainRepo = "https://github.com/AvaloniaUI/Avalonia"; MasterBranch = "master"; + ReleaseBranchPrefix = "release/"; ReleaseConfiguration = "Release"; MSBuildSolution = "./dirs.proj"; @@ -59,12 +61,14 @@ public class Parameters IsRunningOnAzure = buildSystem.IsRunningOnVSTS || buildSystem.IsRunningOnTFS || context.EnvironmentVariable("LOGNAME") == "vsts"; IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; - IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, buildSystem.AppVeyor.Environment.Repository.Name); - IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, buildSystem.AppVeyor.Environment.Repository.Branch); + IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI")); + IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); + IsReleaseBranch = StringComparer.OrdinalIgnoreCase.StartsWith(ReleaseBranchPrefix, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name); IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); IsMyGetRelease = !IsTagged && IsReleasable; + IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; // VERSION Version = context.Argument("force-nuget-version", GetVersion()); @@ -92,9 +96,13 @@ public class Parameters } else if (IsRunningOnAzure) { + if(!IsNuGetRelease) + { // Use AssemblyVersion with Build as version Version += "-build" + context.EnvironmentVariable("BUILD_BUILDID") + "-beta"; - PublishTestResults = true; + } + + PublishTestResults = true; } // DIRECTORIES From 288c56cd3e3a8a2ba79760e5f3a250ccc8f049d9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 14:05:46 +0000 Subject: [PATCH 20/59] fix build script. --- parameters.cake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parameters.cake b/parameters.cake index 8bf6ed8173..acaab8f6b7 100644 --- a/parameters.cake +++ b/parameters.cake @@ -9,6 +9,7 @@ public class Parameters public string MasterBranch { get; private set; } public string ReleasePlatform { get; private set; } public string ReleaseConfiguration { get; private set; } + public string ReleaseBranchPrefix { get; private set; } public string MSBuildSolution { get; private set; } public bool IsLocalBuild { get; private set; } public bool IsRunningOnUnix { get; private set; } @@ -63,7 +64,7 @@ public class Parameters IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI")); IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); - IsReleaseBranch = StringComparer.OrdinalIgnoreCase.StartsWith(ReleaseBranchPrefix, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); + IsReleaseBranch = context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME").ToLower().StartsWith(ReleaseBranchPrefix.ToLower()); IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name); IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); From a1a6c46963dbbdf6ebff54d9bd71477fc4c90f0b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 14:09:44 +0000 Subject: [PATCH 21/59] print isrelease branch. --- build.cake | 1 + 1 file changed, 1 insertion(+) diff --git a/build.cake b/build.cake index c781c0f2e5..f10a12c4e6 100644 --- a/build.cake +++ b/build.cake @@ -50,6 +50,7 @@ Setup(context => Information("IsPullRequest: " + parameters.IsPullRequest); Information("IsMainRepo: " + parameters.IsMainRepo); Information("IsMasterBranch: " + parameters.IsMasterBranch); + Information("IsReleaseBranch: " + parameters.IsReleaseBranch); Information("IsTagged: " + parameters.IsTagged); Information("IsReleasable: " + parameters.IsReleasable); Information("IsMyGetRelease: " + parameters.IsMyGetRelease); From 1db82552a2977f4e246b6ef20c549abc823ef80c Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 30 Oct 2018 17:14:15 +0300 Subject: [PATCH 22/59] Separate previewer properties --- packages/Avalonia/Avalonia.props | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/Avalonia/Avalonia.props b/packages/Avalonia/Avalonia.props index fd7ecc9d12..8234dc4fde 100644 --- a/packages/Avalonia/Avalonia.props +++ b/packages/Avalonia/Avalonia.props @@ -1,10 +1,6 @@ - - - $(MSBuildThisFileDirectory)\..\..\tools\netcoreapp2.0\designer\Avalonia.Designer.HostApp.dll - dotnet exec - - - $(MSBuildThisFileDirectory)\..\..\tools\net461\designer\Avalonia.Designer.HostApp.exe - exe + + + $(MSBuildThisFileDirectory)\..\tools\netcoreapp2.0\designer\Avalonia.Designer.HostApp.dll + $(MSBuildThisFileDirectory)\..\tools\net461\designer\Avalonia.Designer.HostApp.exe From 3979eb99630a3ca6defdb09bede751871af33ea3 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 14:36:58 +0000 Subject: [PATCH 23/59] fix release branch detection. --- parameters.cake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parameters.cake b/parameters.cake index acaab8f6b7..d13e503bd0 100644 --- a/parameters.cake +++ b/parameters.cake @@ -50,7 +50,7 @@ public class Parameters // CONFIGURATION MainRepo = "https://github.com/AvaloniaUI/Avalonia"; MasterBranch = "master"; - ReleaseBranchPrefix = "release/"; + ReleaseBranchPrefix = "refs/heads/release/"; ReleaseConfiguration = "Release"; MSBuildSolution = "./dirs.proj"; @@ -64,7 +64,7 @@ public class Parameters IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI")); IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); - IsReleaseBranch = context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME").ToLower().StartsWith(ReleaseBranchPrefix.ToLower()); + IsReleaseBranch = context.EnvironmentVariable("BUILD_SOURCEBRANCH").ToLower().StartsWith(ReleaseBranchPrefix.ToLower()); IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name); IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); From 5dac868cf0807d825eb76bdbaae35470087e93e4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 30 Oct 2018 15:13:36 +0000 Subject: [PATCH 24/59] bump version number. --- build/SharedVersion.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/SharedVersion.props b/build/SharedVersion.props index 6ca65014b1..b46ac16a79 100644 --- a/build/SharedVersion.props +++ b/build/SharedVersion.props @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> Avalonia - 0.7.0 + 0.7.1 Copyright 2018 © The AvaloniaUI Project https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md https://github.com/AvaloniaUI/Avalonia/ From bbf570198a2d261ac884942a81e00dfa18495b03 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 30 Oct 2018 08:15:43 -0700 Subject: [PATCH 25/59] Always run PublishTestArtifacts unless the build was canceled. --- azure-pipelines.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5156bac3b5..f6929f8dee 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -29,6 +29,7 @@ jobs: inputs: testResultsFormat: 'VSTest' testResultsFiles: '$(Build.SourcesDirectory)/artifacts/test-results/*.trx' + condition: not(canceled()) - job: macOS pool: @@ -77,6 +78,7 @@ jobs: inputs: testResultsFormat: 'VSTest' testResultsFiles: '$(Build.SourcesDirectory)/artifacts/test-results/*.trx' + condition: not(canceled()) - task: PublishBuildArtifacts@1 inputs: @@ -111,6 +113,7 @@ jobs: inputs: testResultsFormat: 'VSTest' testResultsFiles: '$(Build.SourcesDirectory)/artifacts/test-results/*.trx' + condition: not(canceled()) - task: PublishBuildArtifacts@1 inputs: From 4455e698d757028cc579b2bb905e24fa9e01cf14 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Tue, 30 Oct 2018 23:54:09 +0200 Subject: [PATCH 26/59] add easy way to test rendertransform in control catalog --- samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml b/samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml index b428cd1b9f..f7e1c08cac 100644 --- a/samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml +++ b/samples/ControlCatalog/Pages/LayoutTransformControlPage.xaml @@ -19,7 +19,7 @@ - Layout Transform + From 2e430260335f54b9e68646a9c023ec10483950f2 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Wed, 31 Oct 2018 00:36:41 +0200 Subject: [PATCH 27/59] cleanup ImmediateRenderer tests --- .../Rendering/ImmediateRendererTests.cs | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs index 41e1691f28..82294246b1 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests.cs @@ -15,16 +15,13 @@ namespace Avalonia.Visuals.UnitTests.Rendering public void AddDirty_Call_RenderRoot_Invalidate() { var visual = new Mock(); - var child = new Mock(); + var child = new Mock() { CallBase = true }; var renderRoot = visual.As(); visual.As().Setup(v => v.Bounds).Returns(new Rect(0, 0, 400, 400)); child.As().Setup(v => v.Bounds).Returns(new Rect(10, 10, 100, 100)); child.As().Setup(v => v.VisualParent).Returns(visual.Object); - child.As().Setup(v => v.RenderTransform).Returns(default(Transform)); - child.As().Setup(v => v.RenderTransformOrigin).Returns(new RelativePoint(0.5, 0.5, RelativeUnit.Relative)); - child.As().Setup(v => v.TransformToVisual(It.IsAny())).CallBase(); var target = new ImmediateRenderer(visual.Object); @@ -37,16 +34,14 @@ namespace Avalonia.Visuals.UnitTests.Rendering public void AddDirty_With_RenderTransform_Call_RenderRoot_Invalidate() { var visual = new Mock(); - var child = new Mock(); + var child = new Mock() { CallBase = true }; var renderRoot = visual.As(); visual.As().Setup(v => v.Bounds).Returns(new Rect(0, 0, 400, 400)); child.As().Setup(v => v.Bounds).Returns(new Rect(100, 100, 100, 100)); child.As().Setup(v => v.VisualParent).Returns(visual.Object); - child.As().Setup(v => v.RenderTransform).Returns(new ScaleTransform() { ScaleX = 2, ScaleY = 2 }); - child.As().Setup(v => v.RenderTransformOrigin).Returns(new RelativePoint(0.5, 0.5, RelativeUnit.Relative)); - child.As().Setup(v => v.TransformToVisual(It.IsAny())).CallBase(); + child.Object.RenderTransform = new ScaleTransform() { ScaleX = 2, ScaleY = 2 }; var target = new ImmediateRenderer(visual.Object); @@ -58,8 +53,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering [Fact] public void AddDirty_For_Child_Moved_Should_Invalidate_Previous_Bounds() { - var visual = new Mock(); - var child = new Mock(); + var visual = new Mock() { CallBase = true }; + var child = new Mock() { CallBase = true }; var renderRoot = visual.As(); var renderTarget = visual.As(); @@ -72,7 +67,6 @@ namespace Avalonia.Visuals.UnitTests.Rendering Rect childBounds = new Rect(0, 0, 100, 100); child.As().Setup(v => v.Bounds).Returns(() => childBounds); child.As().Setup(v => v.VisualParent).Returns(visual.Object); - child.As().Setup(v => v.TransformToVisual(It.IsAny())).CallBase(); child.As().Setup(v => v.VisualChildren).Returns(new AvaloniaList()); var invalidationCalls = new List(); @@ -100,14 +94,5 @@ namespace Avalonia.Visuals.UnitTests.Rendering //then new position Assert.Equal(new Rect(100, 100, 100, 100), invalidationCalls[2]); } - - public class TestVisual : Visual - { - public new Rect Bounds - { - get => base.Bounds; - set => base.Bounds = value; - } - } } } From b06a5a2991d66c6ff4c7d5c09ec0746d519ed248 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Wed, 31 Oct 2018 00:38:34 +0200 Subject: [PATCH 28/59] fix finally #1998 for immediaterenderer --- .../Rendering/ImmediateRenderer.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs index 967dd24acf..08f3803e9b 100644 --- a/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs @@ -23,7 +23,6 @@ namespace Avalonia.Rendering private readonly IVisual _root; private readonly IRenderRoot _renderRoot; private IRenderTarget _renderTarget; - private Rect _lastPaintBounds; /// /// Initializes a new instance of the class. @@ -46,8 +45,6 @@ namespace Avalonia.Rendering /// public void Paint(Rect rect) { - _lastPaintBounds = rect; - if (_renderTarget == null) { _renderTarget = ((IRenderRoot)_root).CreateRenderTarget(); @@ -129,10 +126,17 @@ namespace Avalonia.Rendering { var bounds = new Rect(visual.Bounds.Size).TransformToAABB(m.Value); - if (_lastPaintBounds != default) + //use transformedbounds as previous render state of the visual bounds + //so we can invalidate old and new bounds of a control in case it moved/shrinked + if (visual.TransformedBounds.HasValue) { - _renderRoot?.Invalidate(_lastPaintBounds); - _lastPaintBounds = default; + var trb = visual.TransformedBounds.Value; + var trBounds = trb.Bounds.TransformToAABB(trb.Transform); + + if (trBounds != bounds) + { + _renderRoot?.Invalidate(trBounds); + } } _renderRoot?.Invalidate(bounds); From 8132bdc162705394e7a9dad115ad3727f690f30b Mon Sep 17 00:00:00 2001 From: ahopper Date: Wed, 31 Oct 2018 09:49:43 +0000 Subject: [PATCH 29/59] end animation cleanly with correct value --- src/Avalonia.Animation/AnimationInstance`1.cs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index 1ad609bce8..04c91ced99 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -141,9 +141,6 @@ namespace Avalonia.Animation } else if (time > iterationEndpoint) { - //Subtract first iteration to properly get the subsequent iteration time - time -= iterationEndpoint; - if (!_iterationDelay & delayEndpoint > TimeSpan.Zero) { delayEndpoint = TimeSpan.Zero; @@ -151,27 +148,32 @@ namespace Avalonia.Animation } //Calculate the current iteration number - _currentIteration = (int)Math.Floor((double)((double)time.Ticks / iterationEndpoint.Ticks)) + 2; + _currentIteration = (int)Math.Floor((double)((double)time.Ticks / iterationEndpoint.Ticks))+1; } else { return; } - time = TimeSpan.FromTicks((long)(time.Ticks % iterationEndpoint.Ticks)); - - if (!_isLooping) - { - if ((_currentIteration > _repeatCount) || (time > iterationEndpoint)) - DoComplete(); - } - - // Determine if the current iteration should have its normalized time inverted. + // Determine if the current iteration should have its normalized time inverted. bool isCurIterReverse = _animationDirection == PlaybackDirection.Normal ? false : _animationDirection == PlaybackDirection.Alternate ? (_currentIteration % 2 == 0) ? false : true : _animationDirection == PlaybackDirection.AlternateReverse ? (_currentIteration % 2 == 0) ? true : false : _animationDirection == PlaybackDirection.Reverse ? true : false; - + + if (!_isLooping) + { + if ((_currentIteration > _repeatCount) || (time >= iterationEndpoint)) + { + var easedTime = _easeFunc.Ease(isCurIterReverse?0.0:1.0); + _lastInterpValue = _interpolator(easedTime, _neutralValue); + + DoComplete(); + return; + } + } + time = TimeSpan.FromTicks((long)(time.Ticks % iterationEndpoint.Ticks)); + if (delayEndpoint > TimeSpan.Zero & time < delayEndpoint) { DoDelay(); From 8864dc8e10e4ac36e6222451176ab93980c005ac Mon Sep 17 00:00:00 2001 From: ahopper Date: Wed, 31 Oct 2018 11:36:01 +0000 Subject: [PATCH 30/59] Fix repeating animations --- src/Avalonia.Animation/AnimationInstance`1.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index 04c91ced99..273c59df0a 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -163,7 +163,8 @@ namespace Avalonia.Animation if (!_isLooping) { - if ((_currentIteration > _repeatCount) || (time >= iterationEndpoint)) + var totalTime = _repeatCount * _duration.Ticks + _delay.Ticks; + if (time.Ticks >= totalTime) { var easedTime = _easeFunc.Ease(isCurIterReverse?0.0:1.0); _lastInterpValue = _interpolator(easedTime, _neutralValue); From 29aad6bc9a35839fc2718ab1b6ec61844b554b1b Mon Sep 17 00:00:00 2001 From: ahopper Date: Wed, 31 Oct 2018 12:09:06 +0000 Subject: [PATCH 31/59] allow for Delay --- src/Avalonia.Animation/AnimationInstance`1.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index 273c59df0a..5f8e33b09a 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -133,6 +133,7 @@ namespace Avalonia.Animation DoPlayStates(); var delayEndpoint = _delay; var iterationEndpoint = delayEndpoint + _duration; + var iterationTime = time; //determine if time is currently in the first iteration. if (time >= TimeSpan.Zero & time <= iterationEndpoint) @@ -141,6 +142,9 @@ namespace Avalonia.Animation } else if (time > iterationEndpoint) { + //Subtract first iteration to properly get the subsequent iteration time + iterationTime -= iterationEndpoint; + if (!_iterationDelay & delayEndpoint > TimeSpan.Zero) { delayEndpoint = TimeSpan.Zero; @@ -148,7 +152,7 @@ namespace Avalonia.Animation } //Calculate the current iteration number - _currentIteration = (int)Math.Floor((double)((double)time.Ticks / iterationEndpoint.Ticks))+1; + _currentIteration = Math.Max(_repeatCount,(int)Math.Floor((double)((double)iterationTime.Ticks / iterationEndpoint.Ticks)) + 2); } else { @@ -173,20 +177,20 @@ namespace Avalonia.Animation return; } } - time = TimeSpan.FromTicks((long)(time.Ticks % iterationEndpoint.Ticks)); + iterationTime = TimeSpan.FromTicks((long)(iterationTime.Ticks % iterationEndpoint.Ticks)); - if (delayEndpoint > TimeSpan.Zero & time < delayEndpoint) + if (delayEndpoint > TimeSpan.Zero & iterationTime < delayEndpoint) { DoDelay(); } else { // Offset the delay time - time -= delayEndpoint; + iterationTime -= delayEndpoint; iterationEndpoint -= delayEndpoint; // Normalize time - var interpVal = (double)time.Ticks / iterationEndpoint.Ticks; + var interpVal = (double)iterationTime.Ticks / iterationEndpoint.Ticks; if (isCurIterReverse) interpVal = 1 - interpVal; From d82a25ea5f72fd51b344c7accff9360e76abddf1 Mon Sep 17 00:00:00 2001 From: ahopper Date: Wed, 31 Oct 2018 12:25:17 +0000 Subject: [PATCH 32/59] fix reversing --- src/Avalonia.Animation/AnimationInstance`1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index 5f8e33b09a..ea033d8cc9 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -152,7 +152,7 @@ namespace Avalonia.Animation } //Calculate the current iteration number - _currentIteration = Math.Max(_repeatCount,(int)Math.Floor((double)((double)iterationTime.Ticks / iterationEndpoint.Ticks)) + 2); + _currentIteration = Math.Min(_repeatCount,(int)Math.Floor((double)((double)iterationTime.Ticks / iterationEndpoint.Ticks)) + 2); } else { From bb0bb392821eefde12ef9fc985c93c2665038e2a Mon Sep 17 00:00:00 2001 From: ahopper Date: Wed, 31 Oct 2018 15:25:42 +0000 Subject: [PATCH 33/59] respect FillMode=Forward if animation stopped part way through --- src/Avalonia.Animation/AnimationInstance`1.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Animation/AnimationInstance`1.cs b/src/Avalonia.Animation/AnimationInstance`1.cs index ea033d8cc9..8184e68d42 100644 --- a/src/Avalonia.Animation/AnimationInstance`1.cs +++ b/src/Avalonia.Animation/AnimationInstance`1.cs @@ -72,10 +72,13 @@ namespace Avalonia.Animation _onCompleteAction = OnComplete; _interpolator = Interpolator; _baseClock = baseClock; - } + } protected override void Unsubscribed() { + //Animation may have been stopped before it has finished + ApplyFinalFill(); + _timerSubscription?.Dispose(); _clock.PlayState = PlayState.Stop; } @@ -98,11 +101,15 @@ namespace Avalonia.Animation } } - private void DoComplete() + private void ApplyFinalFill() { if (_fillMode == FillMode.Forward || _fillMode == FillMode.Both) _targetControl.SetValue(_parent.Property, _lastInterpValue, BindingPriority.LocalValue); + } + private void DoComplete() + { + ApplyFinalFill(); _onCompleteAction?.Invoke(); PublishCompleted(); } @@ -167,10 +174,10 @@ namespace Avalonia.Animation if (!_isLooping) { - var totalTime = _repeatCount * _duration.Ticks + _delay.Ticks; + var totalTime = _iterationDelay ? _repeatCount * ( _duration.Ticks + _delay.Ticks) : _repeatCount * _duration.Ticks + _delay.Ticks; if (time.Ticks >= totalTime) { - var easedTime = _easeFunc.Ease(isCurIterReverse?0.0:1.0); + var easedTime = _easeFunc.Ease(isCurIterReverse ? 0.0 : 1.0); _lastInterpValue = _interpolator(easedTime, _neutralValue); DoComplete(); From 0cbd7b5117dac184c31d18421017749f26cecfde Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Wed, 31 Oct 2018 09:57:34 +0200 Subject: [PATCH 34/59] fix devtools controls highlighting with immediaterenderer issue #1927 --- src/Avalonia.Controls/Primitives/AdornerLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs index 4b58197ef3..5308a062ec 100644 --- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs +++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs @@ -89,7 +89,7 @@ namespace Avalonia.Controls.Primitives control.Clip = clip; } - clip.Rect = bounds.Clip.TransformToAABB(-bounds.Transform); + clip.Rect = bounds.Bounds; } private void ChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) From 4a57d4ddd02f23eeb5effefa14086b64609d9cee Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Wed, 31 Oct 2018 11:00:43 +0200 Subject: [PATCH 35/59] fix click on dropdown when dropdown in other popup fixes #2058 --- src/Avalonia.Controls/DropDown.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/DropDown.cs b/src/Avalonia.Controls/DropDown.cs index 5b7213257d..8596d06d2c 100644 --- a/src/Avalonia.Controls/DropDown.cs +++ b/src/Avalonia.Controls/DropDown.cs @@ -145,7 +145,7 @@ namespace Avalonia.Controls { if (!e.Handled) { - if (((IVisual)e.Source).GetVisualRoot() is PopupRoot) + if (_popup?.PopupRoot != null && ((IVisual)e.Source).GetVisualRoot() == _popup?.PopupRoot) { if (UpdateSelectionFromEventSource(e.Source)) { From 7136750d6b12074ac89fd7ec892bec83d330dc7a Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Wed, 31 Oct 2018 19:27:13 +0200 Subject: [PATCH 36/59] add failing unittests for derivedlist --- .../Collections/AvaloniaListExtenionsTests.cs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs b/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs index b996db8d48..7f118a2c1d 100644 --- a/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs +++ b/tests/Avalonia.Base.UnitTests/Collections/AvaloniaListExtenionsTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Linq; +using System.Linq; using Avalonia.Collections; using Xunit; @@ -82,13 +81,31 @@ namespace Avalonia.Base.UnitTests.Collections Assert.Equal(source, result); } - [Fact] - public void CreateDerivedList_Handles_MoveRange() + [Theory] + [InlineData(0, 2, 3)] + [InlineData(0, 2, 4)] + [InlineData(0, 2, 5)] + [InlineData(0, 4, 4)] + [InlineData(1, 2, 0)] + [InlineData(1, 2, 4)] + [InlineData(1, 2, 5)] + [InlineData(1, 4, 0)] + [InlineData(2, 2, 0)] + [InlineData(2, 2, 1)] + [InlineData(2, 2, 3)] + [InlineData(2, 2, 4)] + [InlineData(2, 2, 5)] + [InlineData(4, 2, 0)] + [InlineData(4, 2, 1)] + [InlineData(4, 2, 3)] + [InlineData(5, 1, 0)] + [InlineData(5, 1, 3)] + public void CreateDerivedList_Handles_MoveRange(int oldIndex, int count, int newIndex) { - var source = new AvaloniaList(new[] { 0, 1, 2, 3 }); + var source = new AvaloniaList(new[] { 0, 1, 2, 3, 4, 5 }); var target = source.CreateDerivedList(x => new Wrapper(x)); - source.MoveRange(1, 2, 0); + source.MoveRange(oldIndex, count, newIndex); var result = target.Select(x => x.Value).ToList(); From aa21fe9d17da5593ffbb81c3600a0dd8e36b1ca9 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Wed, 31 Oct 2018 19:57:31 +0200 Subject: [PATCH 37/59] fix derived list/extensions for moverange --- src/Avalonia.Base/Collections/AvaloniaListExtensions.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs b/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs index 1731950222..58f3413780 100644 --- a/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs +++ b/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs @@ -104,7 +104,12 @@ namespace Avalonia.Collections case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Replace: Remove(e.OldStartingIndex, e.OldItems); - Add(e.NewStartingIndex, e.NewItems); + int newIndex = e.NewStartingIndex; + if(newIndex > e.OldStartingIndex) + { + newIndex -= e.OldItems.Count; + } + Add(newIndex, e.NewItems); break; case NotifyCollectionChangedAction.Remove: From 5e25f25ce24ea914fcd0efec88d5ea68f298eee9 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 2 Nov 2018 10:36:21 +0200 Subject: [PATCH 38/59] fix local cake script build --- parameters.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameters.cake b/parameters.cake index d13e503bd0..4ef7e8e05a 100644 --- a/parameters.cake +++ b/parameters.cake @@ -64,7 +64,7 @@ public class Parameters IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest; IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, context.EnvironmentVariable("BUILD_REPOSITORY_URI")); IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, context.EnvironmentVariable("BUILD_SOURCEBRANCHNAME")); - IsReleaseBranch = context.EnvironmentVariable("BUILD_SOURCEBRANCH").ToLower().StartsWith(ReleaseBranchPrefix.ToLower()); + IsReleaseBranch = (context.EnvironmentVariable("BUILD_SOURCEBRANCH")??"").StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase); IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name); IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); From 81c274328b96ba319711ff15c537086aa97011ce Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 2 Nov 2018 11:04:29 +0200 Subject: [PATCH 39/59] fix tiny tiny nit --- src/Avalonia.Controls/Button.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index 2d80af8e4a..1f3fcbafb3 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -256,7 +256,7 @@ namespace Avalonia.Controls var hittest = this.GetVisualsAt(e.GetPosition(this)); if (ClickMode == ClickMode.Release && - hittest.Any(c => c == this || (c as IStyledElement)?.TemplatedParent == this) == true) + hittest.Any(c => c == this || (c as IStyledElement)?.TemplatedParent == this)) { OnClick(); } From b4dcc14b8d04738760f08724f09c003d4990e81e Mon Sep 17 00:00:00 2001 From: Stano Turza Date: Sat, 3 Nov 2018 14:47:25 +0100 Subject: [PATCH 40/59] make sure pointer is always inside presenter --- src/Avalonia.Controls/TextBox.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index d6c3a1041e..fc1b64a631 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -655,6 +655,8 @@ namespace Avalonia.Controls if (_presenter != null && e.Device.Captured == _presenter) { var point = e.GetPosition(_presenter); + + point = new Point(Math.Max(Math.Min(point.X, _presenter.Bounds.Width - 1), 0), Math.Max(Math.Min(point.Y, _presenter.Bounds.Height - 1), 0)); CaretIndex = SelectionEnd = _presenter.GetCaretIndex(point); } } From 12a49d4336e86ac8f2e6fa144e53a216c049e3a7 Mon Sep 17 00:00:00 2001 From: Stano Turza Date: Sat, 3 Nov 2018 18:15:43 +0100 Subject: [PATCH 41/59] [skia] fixes right aligned textbox selection --- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 2a8f517995..56c5c57f7b 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -121,7 +121,7 @@ namespace Avalonia.Skia int offset = 0; - if (point.X >= (rects[line.Start].X + line.Width) / 2 && line.Length > 0) + if (point.X >= (rects[line.Start].X + line.Width) && line.Length > 0) { offset = line.TextLength > line.Length ? line.Length : (line.Length - 1); From 3dd51660df8f6fb594375de5302fd440abf97952 Mon Sep 17 00:00:00 2001 From: Stano Turza Date: Sun, 4 Nov 2018 15:09:24 +0100 Subject: [PATCH 42/59] use MathUtilities.Clamp --- src/Avalonia.Controls/TextBox.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index fc1b64a631..dc2884b36b 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -14,6 +14,7 @@ using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.Metadata; using Avalonia.Data; +using Avalonia.Utilities; namespace Avalonia.Controls { @@ -656,7 +657,7 @@ namespace Avalonia.Controls { var point = e.GetPosition(_presenter); - point = new Point(Math.Max(Math.Min(point.X, _presenter.Bounds.Width - 1), 0), Math.Max(Math.Min(point.Y, _presenter.Bounds.Height - 1), 0)); + point = new Point(MathUtilities.Clamp(point.X, 0, _presenter.Bounds.Width - 1), MathUtilities.Clamp(point.Y, 0, _presenter.Bounds.Height - 1)); CaretIndex = SelectionEnd = _presenter.GetCaretIndex(point); } } From fd192cf3c21617f767d389df3f6f65bda9bea6aa Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 5 Nov 2018 20:33:11 +0300 Subject: [PATCH 43/59] Fixed Rider support for Avalonia.Native project --- src/Avalonia.Native/.gitignore | 1 + src/Avalonia.Native/Avalonia.Native.csproj | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 src/Avalonia.Native/.gitignore diff --git a/src/Avalonia.Native/.gitignore b/src/Avalonia.Native/.gitignore new file mode 100644 index 0000000000..b1153e777c --- /dev/null +++ b/src/Avalonia.Native/.gitignore @@ -0,0 +1 @@ +Generated/*.cs diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj index 9d6a82a2fb..c8ee73ad5d 100644 --- a/src/Avalonia.Native/Avalonia.Native.csproj +++ b/src/Avalonia.Native/Avalonia.Native.csproj @@ -7,6 +7,8 @@ /usr/bin/castxml /usr/local/bin/castxml true + + $(MSBuildThisFileDirectory)/Generated From da0612e66bcb2c456c9fef042d19cd7e195830ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Mon, 5 Nov 2018 22:34:40 +0100 Subject: [PATCH 44/59] Added base dark theme --- .../Accents/BaseDark.xaml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/Avalonia.Themes.Default/Accents/BaseDark.xaml diff --git a/src/Avalonia.Themes.Default/Accents/BaseDark.xaml b/src/Avalonia.Themes.Default/Accents/BaseDark.xaml new file mode 100644 index 0000000000..95b351b148 --- /dev/null +++ b/src/Avalonia.Themes.Default/Accents/BaseDark.xaml @@ -0,0 +1,56 @@ + From d783d3e1fc5d09316653c88f7b7ff23b179bb0da Mon Sep 17 00:00:00 2001 From: Stano Turza Date: Tue, 6 Nov 2018 10:26:01 +0100 Subject: [PATCH 45/59] do not focus scrollbar --- src/Avalonia.Themes.Default/ScrollBar.xaml | 24 ++++++++++++------- src/Avalonia.Themes.Default/ScrollViewer.xaml | 6 +++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Themes.Default/ScrollBar.xaml b/src/Avalonia.Themes.Default/ScrollBar.xaml index e128e33368..ae40929573 100644 --- a/src/Avalonia.Themes.Default/ScrollBar.xaml +++ b/src/Avalonia.Themes.Default/ScrollBar.xaml @@ -7,7 +7,8 @@ + Grid.Column="0" + Focusable="False"> @@ -21,11 +22,13 @@ Orientation="{TemplateBinding Orientation}"> + Classes="repeattrack" + Focusable="False"/> + Classes="repeattrack" + Focusable="False"/> @@ -38,7 +41,8 @@ + Grid.Column="2" + Focusable="False"> @@ -58,7 +62,8 @@ + Grid.Column="0" + Focusable="False"> @@ -72,11 +77,13 @@ Orientation="{TemplateBinding Orientation}"> + Classes="repeattrack" + Focusable="False"/> + Classes="repeattrack" + Focusable="False"/> @@ -89,7 +96,8 @@ + Grid.Column="2" + Focusable="False"> diff --git a/src/Avalonia.Themes.Default/ScrollViewer.xaml b/src/Avalonia.Themes.Default/ScrollViewer.xaml index c493fb32e3..63440921d6 100644 --- a/src/Avalonia.Themes.Default/ScrollViewer.xaml +++ b/src/Avalonia.Themes.Default/ScrollViewer.xaml @@ -19,14 +19,16 @@ Value="{TemplateBinding HorizontalScrollBarValue, Mode=TwoWay}" ViewportSize="{TemplateBinding HorizontalScrollBarViewportSize}" Visibility="{TemplateBinding HorizontalScrollBarVisibility}" - Grid.Row="1"/> + Grid.Row="1" + Focusable="False"/> + Grid.Column="1" + Focusable="False"/> From c05edaebdccb8ba2df445685aa93bb291c3899f5 Mon Sep 17 00:00:00 2001 From: Stano Turza Date: Tue, 6 Nov 2018 10:26:25 +0100 Subject: [PATCH 46/59] scrollbar PageUp/PageDown handling --- src/Avalonia.Controls/Primitives/ScrollBar.cs | 14 ++++++++++++++ src/Avalonia.Controls/ScrollViewer.cs | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs index 1e290107bb..f0d8c81808 100644 --- a/src/Avalonia.Controls/Primitives/ScrollBar.cs +++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs @@ -128,6 +128,20 @@ namespace Avalonia.Controls.Primitives } } + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.Key == Key.PageUp) + { + LargeDecrement(); + e.Handled = true; + } + else if (e.Key == Key.PageDown) + { + LargeIncrement(); + e.Handled = true; + } + } + protected override void OnTemplateApplied(TemplateAppliedEventArgs e) { base.OnTemplateApplied(e); diff --git a/src/Avalonia.Controls/ScrollViewer.cs b/src/Avalonia.Controls/ScrollViewer.cs index 39854e0071..264b1fd2ce 100644 --- a/src/Avalonia.Controls/ScrollViewer.cs +++ b/src/Avalonia.Controls/ScrollViewer.cs @@ -4,6 +4,7 @@ using System; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; +using Avalonia.Input; namespace Avalonia.Controls { @@ -441,5 +442,19 @@ namespace Avalonia.Controls RaisePropertyChanged(VerticalScrollBarValueProperty, 0, VerticalScrollBarValue); RaisePropertyChanged(VerticalScrollBarViewportSizeProperty, 0, VerticalScrollBarViewportSize); } + + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.Key == Key.PageUp) + { + VerticalScrollBarValue = Math.Max(_offset.Y - _viewport.Height, 0); + e.Handled = true; + } + else if (e.Key == Key.PageDown) + { + VerticalScrollBarValue = Math.Min(_offset.Y + _viewport.Height, VerticalScrollBarMaximum); + e.Handled = true; + } + } } } From aefec666116e3a4baf2163942b806b6f4b9dcf9a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 6 Nov 2018 10:36:08 +0000 Subject: [PATCH 47/59] [OSX] reset lastKeyHandled flag when performKeyEquivalent is called since this indicated a key being pressed also. --- native/Avalonia.Native/src/OSX/window.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 76243493c4..362b765b3d 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -963,7 +963,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent - (BOOL)performKeyEquivalent:(NSEvent *)event { - return _lastKeyHandled; + bool result = _lastKeyHandled; + + _lastKeyHandled = false; + + return result; } - (void)keyDown:(NSEvent *)event From c1fda553e6ac7c841e34feb678f986f405a1fd75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 6 Nov 2018 12:01:20 +0100 Subject: [PATCH 48/59] Fix header styles --- samples/ControlCatalog/App.xaml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml index 95d515ec60..19a22bb6ed 100644 --- a/samples/ControlCatalog/App.xaml +++ b/samples/ControlCatalog/App.xaml @@ -2,23 +2,16 @@ - - - - - - + + From d07217b59a1920bbb5f6f44d04249bd96e65e0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 6 Nov 2018 12:01:36 +0100 Subject: [PATCH 49/59] Enable full theme support for main view --- samples/ControlCatalog/MainView.xaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index ec3bf799b4..effb805728 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -1,6 +1,9 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Background="{DynamicResource ThemeBackgroundBrush}" + TextBlock.Foreground="{DynamicResource ThemeForegroundBrush}" + TextBlock.FontSize="{DynamicResource FontSizeNormal}"> From 779cdec09356f7c825b5f70f87b5b4732a6b0036 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 7 Nov 2018 15:24:49 +0000 Subject: [PATCH 50/59] initial work to fixing clipboard text encoding issues. --- native/Avalonia.Native/inc/avalonia-native.h | 8 ++- .../project.pbxproj | 6 ++ native/Avalonia.Native/src/OSX/AvnString.h | 14 +++++ native/Avalonia.Native/src/OSX/AvnString.mm | 55 +++++++++++++++++++ native/Avalonia.Native/src/OSX/clipboard.mm | 15 +++-- src/Avalonia.Native/ClipboardImpl.cs | 9 +-- 6 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 native/Avalonia.Native/src/OSX/AvnString.h create mode 100644 native/Avalonia.Native/src/OSX/AvnString.mm diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index 0c965b7498..1d5a112929 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -173,6 +173,12 @@ public: virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) = 0; }; +AVNCOM(IAvnString, 17) : IUnknown +{ + virtual HRESULT GetPointer(void**retOut) = 0; + virtual HRESULT GetLength(int*ret) = 0; +}; + AVNCOM(IAvnWindowBase, 02) : IUnknown { virtual HRESULT Show() = 0; @@ -315,7 +321,7 @@ AVNCOM(IAvnScreens, 0e) : IUnknown AVNCOM(IAvnClipboard, 0f) : IUnknown { - virtual HRESULT GetText (void** retOut) = 0; + virtual HRESULT GetText (IAvnString** ppv ) = 0; virtual HRESULT SetText (char* text) = 0; virtual HRESULT Clear() = 0; }; diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj index bd8ac481a8..cc74d5669f 100644 --- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj +++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; }; 37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; }; + 37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; }; 37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; }; 5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; }; 5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; }; @@ -26,6 +27,8 @@ 37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = ""; }; 37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = ""; }; 37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = ""; }; + 37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = ""; }; + 37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = ""; }; 37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = ""; }; 5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = ""; }; 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = ""; }; @@ -65,6 +68,8 @@ AB7A61E62147C814003C5833 = { isa = PBXGroup; children = ( + 37DDA9B121933371002E132B /* AvnString.h */, + 37DDA9AF219330F8002E132B /* AvnString.mm */, 37A4E71A2178846A00EACBCD /* headers */, AB573DC3217605E400D389A2 /* gl.mm */, 5BF943652167AD1D009CAE35 /* cursor.h */, @@ -161,6 +166,7 @@ files = ( 5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */, 5B21A982216530F500CEE36E /* cursor.mm in Sources */, + 37DDA9B0219330F8002E132B /* AvnString.mm in Sources */, AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */, 37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */, 37A517B32159597E00FBA241 /* Screens.mm in Sources */, diff --git a/native/Avalonia.Native/src/OSX/AvnString.h b/native/Avalonia.Native/src/OSX/AvnString.h new file mode 100644 index 0000000000..9a8f5a1318 --- /dev/null +++ b/native/Avalonia.Native/src/OSX/AvnString.h @@ -0,0 +1,14 @@ +// +// AvnString.h +// Avalonia.Native.OSX +// +// Created by Dan Walmsley on 07/11/2018. +// Copyright © 2018 Avalonia. All rights reserved. +// + +#ifndef AvnString_h +#define AvnString_h + +extern IAvnString* CreateAvnString(NSString* string); + +#endif /* AvnString_h */ diff --git a/native/Avalonia.Native/src/OSX/AvnString.mm b/native/Avalonia.Native/src/OSX/AvnString.mm new file mode 100644 index 0000000000..a16c286634 --- /dev/null +++ b/native/Avalonia.Native/src/OSX/AvnString.mm @@ -0,0 +1,55 @@ +// +// AvnString.m +// Avalonia.Native.OSX +// +// Created by Dan Walmsley on 07/11/2018. +// Copyright © 2018 Avalonia. All rights reserved. +// + +#include "common.h" + +class AvnStringImpl : public virtual ComSingleObject +{ +private: + NSString* _string; + +public: + FORWARD_IUNKNOWN() + + AvnStringImpl(NSString* string) + { + _string = string; + } + + virtual HRESULT GetPointer(void**retOut) override + { + @autoreleasepool + { + if(retOut == nullptr) + { + return E_POINTER; + } + + *retOut = (void*)_string.UTF8String; + + return S_OK; + } + } + + virtual HRESULT GetLength(int*retOut) override + { + if(retOut == nullptr) + { + return E_POINTER; + } + + *retOut = (int)_string.length; + + return S_OK; + } +}; + +IAvnString* CreateAvnString(NSString* string) +{ + return new AvnStringImpl(string); +} diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm index 19e5c25801..f941e8ca6c 100644 --- a/native/Avalonia.Native/src/OSX/clipboard.mm +++ b/native/Avalonia.Native/src/OSX/clipboard.mm @@ -2,20 +2,25 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. #include "common.h" +#include "AvnString.h" class Clipboard : public ComSingleObject { public: FORWARD_IUNKNOWN() - virtual HRESULT GetText (void** retOut) override + virtual HRESULT GetText (IAvnString** retOut) override { @autoreleasepool { - NSString *str = [[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]; - *retOut = (void *)str.UTF8String; - } + if(retOut == nullptr) + { + return E_POINTER; + } + + *retOut = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]); - return S_OK; + return S_OK; + } } virtual HRESULT SetText (char* text) override diff --git a/src/Avalonia.Native/ClipboardImpl.cs b/src/Avalonia.Native/ClipboardImpl.cs index d54bc95fbb..a2a1416645 100644 --- a/src/Avalonia.Native/ClipboardImpl.cs +++ b/src/Avalonia.Native/ClipboardImpl.cs @@ -24,12 +24,13 @@ namespace Avalonia.Native return Task.CompletedTask; } - public Task GetTextAsync() + public unsafe Task GetTextAsync() { - var outPtr = _native.GetText(); - var text = Marshal.PtrToStringAnsi(outPtr); + var text = _native.GetText(); - return Task.FromResult(text); + var result = System.Text.Encoding.UTF8.GetString((byte*)text.GetPointer(), text.GetLength()); + + return Task.FromResult(result); } public Task SetTextAsync(string text) From b224a21433f58540fdd24aa6ebb99bba1aa3e4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 7 Nov 2018 16:24:55 +0100 Subject: [PATCH 51/59] Set window Foreground property to enable theming --- src/Avalonia.Themes.Default/Window.xaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Themes.Default/Window.xaml b/src/Avalonia.Themes.Default/Window.xaml index 611f8ebece..2514422ce8 100644 --- a/src/Avalonia.Themes.Default/Window.xaml +++ b/src/Avalonia.Themes.Default/Window.xaml @@ -1,5 +1,6 @@ \ No newline at end of file + From c9aff424a5c3fd4c18042100b1c63513db4918b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 7 Nov 2018 16:25:27 +0100 Subject: [PATCH 52/59] Remove not required properties --- samples/ControlCatalog/MainView.xaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index effb805728..ec3bf799b4 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -1,9 +1,6 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> From c3ec5c543f7cc3d2083120a6267ee0ebff7aef03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 7 Nov 2018 17:16:01 +0100 Subject: [PATCH 53/59] Added user control styling support --- src/Avalonia.Controls/UserControl.cs | 2 +- src/Avalonia.Themes.Default/DefaultTheme.xaml | 1 + src/Avalonia.Themes.Default/UserControl.xaml | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/Avalonia.Themes.Default/UserControl.xaml diff --git a/src/Avalonia.Controls/UserControl.cs b/src/Avalonia.Controls/UserControl.cs index e063a65e09..3f51f613a4 100644 --- a/src/Avalonia.Controls/UserControl.cs +++ b/src/Avalonia.Controls/UserControl.cs @@ -28,7 +28,7 @@ namespace Avalonia.Controls } /// - Type IStyleable.StyleKey => typeof(ContentControl); + Type IStyleable.StyleKey => typeof(UserControl); /// void INameScope.Register(string name, object element) diff --git a/src/Avalonia.Themes.Default/DefaultTheme.xaml b/src/Avalonia.Themes.Default/DefaultTheme.xaml index 2b9132ee56..0bd91c8f1e 100644 --- a/src/Avalonia.Themes.Default/DefaultTheme.xaml +++ b/src/Avalonia.Themes.Default/DefaultTheme.xaml @@ -35,6 +35,7 @@ + diff --git a/src/Avalonia.Themes.Default/UserControl.xaml b/src/Avalonia.Themes.Default/UserControl.xaml new file mode 100644 index 0000000000..2bf5f19698 --- /dev/null +++ b/src/Avalonia.Themes.Default/UserControl.xaml @@ -0,0 +1,15 @@ + From 06a6059a1e4b50204ca5162b7eb1f77045b79a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 7 Nov 2018 17:27:56 +0100 Subject: [PATCH 54/59] Fix failing test --- tests/Avalonia.Controls.UnitTests/UserControlTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/UserControlTests.cs b/tests/Avalonia.Controls.UnitTests/UserControlTests.cs index 738c54594e..36fde09cdb 100644 --- a/tests/Avalonia.Controls.UnitTests/UserControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/UserControlTests.cs @@ -23,7 +23,7 @@ namespace Avalonia.Controls.UnitTests { Styles = { - new Style(x => x.OfType()) + new Style(x => x.OfType()) { Setters = new[] { From 55486faa43c363852bb1d04ed24d6405a10e9ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 7 Nov 2018 17:32:04 +0100 Subject: [PATCH 55/59] Fix type --- tests/Avalonia.Controls.UnitTests/UserControlTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/UserControlTests.cs b/tests/Avalonia.Controls.UnitTests/UserControlTests.cs index 36fde09cdb..6da771217c 100644 --- a/tests/Avalonia.Controls.UnitTests/UserControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/UserControlTests.cs @@ -40,7 +40,7 @@ namespace Avalonia.Controls.UnitTests private FuncControlTemplate GetTemplate() { - return new FuncControlTemplate(parent => + return new FuncControlTemplate(parent => { return new Border { From f6d080feecd1a68ce5ba8028dbdab37b5e8e8264 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 8 Nov 2018 17:20:51 +0000 Subject: [PATCH 56/59] [OSX] fix pasting from clipboard --- native/Avalonia.Native/inc/avalonia-native.h | 6 +++--- native/Avalonia.Native/src/OSX/AvnString.mm | 4 ++-- native/Avalonia.Native/src/OSX/clipboard.mm | 11 ++--------- src/Avalonia.Native/ClipboardImpl.cs | 9 +++++---- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index 1d5a112929..b9e16e6643 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -175,8 +175,8 @@ public: AVNCOM(IAvnString, 17) : IUnknown { - virtual HRESULT GetPointer(void**retOut) = 0; - virtual HRESULT GetLength(int*ret) = 0; + virtual HRESULT Pointer(void**retOut) = 0; + virtual HRESULT Length(int*ret) = 0; }; AVNCOM(IAvnWindowBase, 02) : IUnknown @@ -321,7 +321,7 @@ AVNCOM(IAvnScreens, 0e) : IUnknown AVNCOM(IAvnClipboard, 0f) : IUnknown { - virtual HRESULT GetText (IAvnString** ppv ) = 0; + virtual IAvnString* GetText () = 0; virtual HRESULT SetText (char* text) = 0; virtual HRESULT Clear() = 0; }; diff --git a/native/Avalonia.Native/src/OSX/AvnString.mm b/native/Avalonia.Native/src/OSX/AvnString.mm index a16c286634..b491cf2a92 100644 --- a/native/Avalonia.Native/src/OSX/AvnString.mm +++ b/native/Avalonia.Native/src/OSX/AvnString.mm @@ -21,7 +21,7 @@ public: _string = string; } - virtual HRESULT GetPointer(void**retOut) override + virtual HRESULT Pointer(void**retOut) override { @autoreleasepool { @@ -36,7 +36,7 @@ public: } } - virtual HRESULT GetLength(int*retOut) override + virtual HRESULT Length(int*retOut) override { if(retOut == nullptr) { diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm index f941e8ca6c..8f95433f64 100644 --- a/native/Avalonia.Native/src/OSX/clipboard.mm +++ b/native/Avalonia.Native/src/OSX/clipboard.mm @@ -8,18 +8,11 @@ class Clipboard : public ComSingleObject { public: FORWARD_IUNKNOWN() - virtual HRESULT GetText (IAvnString** retOut) override + virtual IAvnString* GetText () override { @autoreleasepool { - if(retOut == nullptr) - { - return E_POINTER; - } - - *retOut = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]); - - return S_OK; + return CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]); } } diff --git a/src/Avalonia.Native/ClipboardImpl.cs b/src/Avalonia.Native/ClipboardImpl.cs index a2a1416645..9a49976683 100644 --- a/src/Avalonia.Native/ClipboardImpl.cs +++ b/src/Avalonia.Native/ClipboardImpl.cs @@ -26,11 +26,12 @@ namespace Avalonia.Native public unsafe Task GetTextAsync() { - var text = _native.GetText(); - - var result = System.Text.Encoding.UTF8.GetString((byte*)text.GetPointer(), text.GetLength()); + using (var text = _native.GetText()) + { + var result = System.Text.Encoding.UTF8.GetString((byte*)text.Pointer(), text.Length()); - return Task.FromResult(result); + return Task.FromResult(result); + } } public Task SetTextAsync(string text) From d06ed4a7dba0729b303b84b02014052b0b0e0718 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 8 Nov 2018 17:38:28 +0000 Subject: [PATCH 57/59] [OSX] correctly use UTF8 encoded text for passing strings. SetTitle on Window, SetText on Clipboard. --- native/Avalonia.Native/inc/avalonia-native.h | 4 ++-- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ native/Avalonia.Native/src/OSX/clipboard.mm | 4 ++-- native/Avalonia.Native/src/OSX/window.mm | 4 ++-- src/Avalonia.Native/ClipboardImpl.cs | 6 +++++- src/Avalonia.Native/WindowImpl.cs | 6 +++++- 6 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index b9e16e6643..f353509346 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -216,7 +216,7 @@ AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase virtual HRESULT ShowDialog (IUnknown**ppv) = 0; virtual HRESULT SetCanResize(bool value) = 0; virtual HRESULT SetHasDecorations(bool value) = 0; - virtual HRESULT SetTitle (const char* title) = 0; + virtual HRESULT SetTitle (void* utf8Title) = 0; virtual HRESULT SetTitleBarColor (AvnColor color) = 0; virtual HRESULT SetWindowState(AvnWindowState state) = 0; virtual HRESULT GetWindowState(AvnWindowState*ret) = 0; @@ -322,7 +322,7 @@ AVNCOM(IAvnScreens, 0e) : IUnknown AVNCOM(IAvnClipboard, 0f) : IUnknown { virtual IAvnString* GetText () = 0; - virtual HRESULT SetText (char* text) = 0; + virtual HRESULT SetText (void* utf8Text) = 0; virtual HRESULT Clear() = 0; }; diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm index 8f95433f64..be77ff52d8 100644 --- a/native/Avalonia.Native/src/OSX/clipboard.mm +++ b/native/Avalonia.Native/src/OSX/clipboard.mm @@ -16,13 +16,13 @@ public: } } - virtual HRESULT SetText (char* text) override + virtual HRESULT SetText (void* utf8String) override { @autoreleasepool { NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; [pasteBoard clearContents]; - [pasteBoard setString:@(text) forType:NSPasteboardTypeString]; + [pasteBoard setString:[NSString stringWithUTF8String:(const char*)utf8String] forType:NSPasteboardTypeString]; } return S_OK; diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 362b765b3d..16b21efcd5 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -530,11 +530,11 @@ private: } } - virtual HRESULT SetTitle (const char* title) override + virtual HRESULT SetTitle (void* utf8title) override { @autoreleasepool { - _lastTitle = [NSString stringWithUTF8String:title]; + _lastTitle = [NSString stringWithUTF8String:(const char*)utf8title]; [Window setTitle:_lastTitle]; [Window setTitleVisibility:NSWindowTitleVisible]; diff --git a/src/Avalonia.Native/ClipboardImpl.cs b/src/Avalonia.Native/ClipboardImpl.cs index 9a49976683..c756a6d9c2 100644 --- a/src/Avalonia.Native/ClipboardImpl.cs +++ b/src/Avalonia.Native/ClipboardImpl.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Runtime.InteropServices; using Avalonia.Input.Platform; using Avalonia.Native.Interop; +using Avalonia.Platform.Interop; namespace Avalonia.Native { @@ -40,7 +41,10 @@ namespace Avalonia.Native if (text != null) { - _native.SetText(text); + using (var buffer = new Utf8Buffer(text)) + { + _native.SetText(buffer.DangerousGetHandle()); + } } return Task.CompletedTask; diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 5d30408e52..3b1b4ff3f9 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -5,6 +5,7 @@ using System; using Avalonia.Controls; using Avalonia.Native.Interop; using Avalonia.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Native { @@ -68,7 +69,10 @@ namespace Avalonia.Native public void SetTitle(string title) { - _native.SetTitle(title); + using (var buffer = new Utf8Buffer(title)) + { + _native.SetTitle(buffer.DangerousGetHandle()); + } } public WindowState WindowState From 5af1c1784a8dd58491b9e834bf97c489a235cc95 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 8 Nov 2018 17:43:36 +0000 Subject: [PATCH 58/59] [Avalonia.Native OSX] fix api for clipboard --- native/Avalonia.Native/inc/avalonia-native.h | 2 +- native/Avalonia.Native/src/OSX/clipboard.mm | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index f353509346..0e3edaa2dc 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -321,7 +321,7 @@ AVNCOM(IAvnScreens, 0e) : IUnknown AVNCOM(IAvnClipboard, 0f) : IUnknown { - virtual IAvnString* GetText () = 0; + virtual HRESULT GetText (IAvnString**ppv) = 0; virtual HRESULT SetText (void* utf8Text) = 0; virtual HRESULT Clear() = 0; }; diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm index be77ff52d8..53c1fe3c2c 100644 --- a/native/Avalonia.Native/src/OSX/clipboard.mm +++ b/native/Avalonia.Native/src/OSX/clipboard.mm @@ -8,11 +8,18 @@ class Clipboard : public ComSingleObject { public: FORWARD_IUNKNOWN() - virtual IAvnString* GetText () override + virtual HRESULT GetText (IAvnString**ppv) override { @autoreleasepool { - return CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]); + if(ppv == nullptr) + { + return E_POINTER; + } + + *ppv = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]); + + return S_OK; } } From 7762fa6079b06850087b1d1888b7b3a463b2541a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 8 Nov 2018 17:46:52 +0000 Subject: [PATCH 59/59] remove plist file --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d..0000000000 --- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - -