From 6c96f690618cd9a25ac42c8b7f9d8015a784110e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 14 Jul 2017 10:02:26 +0200 Subject: [PATCH 01/11] Only show tooltip when pointer still over control. Make sure the pointer is still over the control when the timer fires to show a tooltip. --- src/Avalonia.Controls/ToolTip.cs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/Avalonia.Controls/ToolTip.cs b/src/Avalonia.Controls/ToolTip.cs index 22bc589a36..e1b69637af 100644 --- a/src/Avalonia.Controls/ToolTip.cs +++ b/src/Avalonia.Controls/ToolTip.cs @@ -106,24 +106,28 @@ namespace Avalonia.Controls if (control != null && control.IsVisible && control.GetVisualRoot() != null) { var cp = (control.GetVisualRoot() as IInputRoot)?.MouseDevice?.GetPosition(control); - var position = control.PointToScreen(cp ?? new Point(0, 0)) + new Vector(0, 22); - if (s_popup == null) + if (cp.HasValue && control.IsVisible && new Rect(control.Bounds.Size).Contains(cp.Value)) { - s_popup = new PopupRoot(); - s_popup.Content = new ToolTip(); - } - else - { - ((ISetLogicalParent)s_popup).SetParent(null); - } + var position = control.PointToScreen(cp.Value) + new Vector(0, 22); + + if (s_popup == null) + { + s_popup = new PopupRoot(); + s_popup.Content = new ToolTip(); + } + else + { + ((ISetLogicalParent)s_popup).SetParent(null); + } ((ISetLogicalParent)s_popup).SetParent(control); - ((ToolTip)s_popup.Content).Content = GetTip(control); - s_popup.Position = position; - s_popup.Show(); + ((ToolTip)s_popup.Content).Content = GetTip(control); + s_popup.Position = position; + s_popup.Show(); - s_current = control; + s_current = control; + } } } From 76c90df2da048f46327d26ead6f5d0db1a76c53f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2017 04:12:40 +0300 Subject: [PATCH 02/11] Initial implementation for Direct2D rendering for WPF integration --- build/SharpDX.props | 1 + samples/interop/WindowsInteropTest/Program.cs | 2 +- .../ExternalRenderTarget.cs | 11 +- .../IExternalDirect2DRenderTargetSurface.cs | 3 +- .../Avalonia.Win32.Interop.csproj | 9 + .../Wpf/Direct2DImageSurface.cs | 206 ++++++++++++++++++ .../Wpf/WpfTopLevelImpl.cs | 11 +- .../Wpf/WritableBitmapSurface.cs | 10 +- 8 files changed, 233 insertions(+), 20 deletions(-) create mode 100644 src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs diff --git a/build/SharpDX.props b/build/SharpDX.props index e381bc03e6..0eb910e71e 100644 --- a/build/SharpDX.props +++ b/build/SharpDX.props @@ -3,6 +3,7 @@ + diff --git a/samples/interop/WindowsInteropTest/Program.cs b/samples/interop/WindowsInteropTest/Program.cs index 4770688ecf..fac06d74b0 100644 --- a/samples/interop/WindowsInteropTest/Program.cs +++ b/samples/interop/WindowsInteropTest/Program.cs @@ -15,7 +15,7 @@ namespace WindowsInteropTest { System.Windows.Forms.Application.EnableVisualStyles(); System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false); - AppBuilder.Configure().UseWin32().UseSkia().SetupWithoutStarting(); + AppBuilder.Configure().UseWin32().UseDirect2D1().SetupWithoutStarting(); System.Windows.Forms.Application.Run(new SelectorForm()); } } diff --git a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs index b1c0e7e30a..307048f7b4 100644 --- a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs +++ b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs @@ -15,7 +15,6 @@ namespace Avalonia.Direct2D1 { private readonly IExternalDirect2DRenderTargetSurface _externalRenderTargetProvider; private readonly DirectWriteFactory _dwFactory; - private SharpDX.Direct2D1.RenderTarget _target; public ExternalRenderTarget(IExternalDirect2DRenderTargetSurface externalRenderTargetProvider, DirectWriteFactory dwFactory) { @@ -25,15 +24,14 @@ namespace Avalonia.Direct2D1 public void Dispose() { - _target?.Dispose(); - _target = null; + _externalRenderTargetProvider.DestroyRenderTarget(); } public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) { - _target = _target ?? _externalRenderTargetProvider.CreateRenderTarget(); + var target = _externalRenderTargetProvider.GetOrCreateRenderTarget(); _externalRenderTargetProvider.BeforeDrawing(); - return new DrawingContextImpl(visualBrushRenderer, _target, _dwFactory, null, () => + return new DrawingContextImpl(visualBrushRenderer, target, _dwFactory, null, () => { try { @@ -41,8 +39,7 @@ namespace Avalonia.Direct2D1 } catch (SharpDXException ex) when ((uint) ex.HResult == 0x8899000C) // D2DERR_RECREATE_TARGET { - _target?.Dispose(); - _target = null; + _externalRenderTargetProvider.DestroyRenderTarget(); } }); } diff --git a/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs b/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs index 0774c25937..aad51f46d5 100644 --- a/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs +++ b/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs @@ -8,7 +8,8 @@ namespace Avalonia.Direct2D1 { public interface IExternalDirect2DRenderTargetSurface { - SharpDX.Direct2D1.RenderTarget CreateRenderTarget(); + SharpDX.Direct2D1.RenderTarget GetOrCreateRenderTarget(); + void DestroyRenderTarget(); void BeforeDrawing(); void AfterDrawing(); } diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj index c5cd2ab64d..099a7f4074 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj @@ -49,6 +49,7 @@ + @@ -104,10 +105,18 @@ {6417e941-21bc-467b-a771-0de389353ce6} Avalonia.Markup + + {3e908f67-5543-4879-a1dc-08eace79b3cd} + Avalonia.Direct2D1 + {811a76cf-1cf6-440f-963b-bbe31bd72a82} Avalonia.Win32 + + true + + \ No newline at end of file diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs new file mode 100644 index 0000000000..303e0850aa --- /dev/null +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Interop; +using Avalonia.Direct2D1; +using SharpDX; +using SharpDX.Direct2D1; +using SharpDX.Direct3D11; +using SharpDX.Direct3D9; +using SharpDX.DXGI; +using AlphaMode = SharpDX.Direct2D1.AlphaMode; +using Device = SharpDX.Direct3D11.Device; +using Format = SharpDX.DXGI.Format; +using MapFlags = SharpDX.Direct3D11.MapFlags; +using PresentParameters = SharpDX.DXGI.PresentParameters; +using RenderTarget = SharpDX.Direct2D1.RenderTarget; +using Surface = SharpDX.DXGI.Surface; +using SwapEffect = SharpDX.DXGI.SwapEffect; +using Usage = SharpDX.Direct3D9.Usage; + +namespace Avalonia.Win32.Interop.Wpf +{ + class Direct2DImageSurface : IExternalDirect2DRenderTargetSurface + { + class Pair: IDisposable + { + public SharpDX.Direct3D9.Surface Texture { get; } + public SharpDX.Direct3D11.Resource D3D11Resource { get; } + public SharpDX.Direct3D11.Resource StagingResource { get; } + public RenderTarget Target { get;} + public Size Size { get; } + + public Pair(Size size, Vector dpi) + { + int width = (int) size.Width; + int height = (int) size.Height; + using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription + { + Width = width, + Height = height, + ArraySize = 1, + MipLevels = 1, + Format = Format.B8G8R8A8_UNorm, + Usage = ResourceUsage.Default, + SampleDescription = new SampleDescription(1, 0), + BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, + OptionFlags = ResourceOptionFlags.Shared + })) + using (var surface = texture.QueryInterface()) + using (var resource = texture.QueryInterface()) + { + D3D11Resource = texture.QueryInterface(); + var handle = resource.SharedHandle; + using (var texture9 = new Texture(s_d3DDevice, texture.Description.Width, + texture.Description.Height, 1, + Usage.RenderTarget, SharpDX.Direct3D9.Format.A8R8G8B8, Pool.Default, ref handle)) + Texture = texture9.GetSurfaceLevel(0); + Target = new RenderTarget(AvaloniaLocator.Current.GetService(), surface, + new RenderTargetProperties + { + DpiX = (float) dpi.X, + DpiY = (float) dpi.Y, + MinLevel = FeatureLevel.Level_10, + PixelFormat = new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied), + + }); + } + using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription + { + Width = Math.Min(width, 16), + Height = Math.Min(height, 16), + ArraySize = 1, + MipLevels = 1, + Format = Format.B8G8R8A8_UNorm, + Usage = ResourceUsage.Staging, + SampleDescription = new SampleDescription(1, 0), + CpuAccessFlags = CpuAccessFlags.Read + })) + StagingResource = texture.QueryInterface(); + Size = size; + } + + public void Dispose() + { + Texture?.Dispose(); + Target?.Dispose(); + D3D11Resource?.Dispose(); + StagingResource?.Dispose(); + } + + public void Flush() + { + + s_dxDevice.ImmediateContext.CopySubresourceRegion(D3D11Resource, 0, + new ResourceRegion(0, 0, 0, 1, 1, 1), StagingResource, 0, 0, 0, 0); + s_dxDevice.ImmediateContext.MapSubresource(StagingResource, 0, MapMode.Read, MapFlags.None); + s_dxDevice.ImmediateContext.UnmapSubresource(StagingResource, 0); + + } + } + + private D3DImage _image; + private Pair _backBuffer; + private Pair _frontBuffer; + private readonly WpfTopLevelImpl _impl; + private static Device s_dxDevice; + private static Direct3DEx s_d3DContext; + private static DeviceEx s_d3DDevice; + + + [DllImport("user32.dll", SetLastError = false)] + private static extern IntPtr GetDesktopWindow(); + void EnsureDirectX() + { + if(s_d3DDevice != null) + return; + s_d3DContext = new Direct3DEx(); + + SharpDX.Direct3D9.PresentParameters presentparams = new SharpDX.Direct3D9.PresentParameters + { + Windowed = true, + SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard, + DeviceWindowHandle = GetDesktopWindow(), + PresentationInterval = PresentInterval.Default + }; + s_dxDevice = s_dxDevice ?? AvaloniaLocator.Current.GetService() + .QueryInterface(); + s_d3DDevice = new DeviceEx(s_d3DContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams); + + } + + public Direct2DImageSurface(WpfTopLevelImpl impl) + { + _impl = impl; + } + + public RenderTarget GetOrCreateRenderTarget() + { + EnsureDirectX(); + var scale = _impl.GetScaling(); + var size = new Size(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y); + var dpi = scale * 96; + + if (_backBuffer!=null && _backBuffer.Size == size) + return _backBuffer.Target; + + if (_image == null) + _image = new DX11Image(); + _impl.ImageSource = _image; + + + + RemoveAndDispose(ref _backBuffer); + if (size == default(Size)) + { + RemoveAndDispose(ref _frontBuffer); + _image.Lock(); + _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); + _image.Unlock(); + return null; + } + _backBuffer = new Pair(size, dpi); + + return _backBuffer.Target; + } + + void RemoveAndDispose(ref T d) where T : IDisposable + { + d?.Dispose(); + d = default(T); + } + + void DoSwap() + { + + } + + void Swap() + { + var oldFront = _frontBuffer; + _frontBuffer = _backBuffer; + _backBuffer = oldFront; + _frontBuffer.Flush(); + _image.Lock(); + _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _frontBuffer?.Texture?.NativePointer ?? IntPtr.Zero, true); + _image.AddDirtyRect(new Int32Rect(0, 0, _image.PixelWidth, _image.PixelHeight)); + _image.Unlock(); + } + + public void DestroyRenderTarget() + { + //? + } + + public void BeforeDrawing() + { + + } + + public void AfterDrawing() => Swap(); + } +} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 0620c6cc57..b5715d43d5 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -60,7 +60,7 @@ namespace Avalonia.Win32.Interop.Wpf PresentationSource.AddSourceChangedHandler(this, OnSourceChanged); _hook = WndProc; _ttl = this; - _surfaces = new object[] {new WritableBitmapSurface(this)}; + _surfaces = new object[] {new WritableBitmapSurface(this), new Direct2DImageSurface(this)}; _mouse = new WpfMouseDevice(this); _keyboard = AvaloniaLocator.Current.GetService(); @@ -224,6 +224,13 @@ namespace Avalonia.Win32.Interop.Wpf Action ITopLevelImpl.ScalingChanged { get; set; } Action ITopLevelImpl.Closed { get; set; } public new event Action LostFocus; - + + internal Vector GetScaling() + { + var src = PresentationSource.FromVisual(this)?.CompositionTarget; + if (src == null) + return new Vector(1, 1); + return new Vector(src.TransformToDevice.M11, src.TransformToDevice.M22); + } } } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs index 1dd1cb983a..0f8752fb8d 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs @@ -24,7 +24,7 @@ namespace Avalonia.Win32.Interop.Wpf public ILockedFramebuffer Lock() { - var scale = GetScaling(); + var scale = _impl.GetScaling(); var size = new Size(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y); var dpi = scale * 96; if (_bitmap == null || _bitmap.PixelWidth != (int) size.Width || _bitmap.PixelHeight != (int) size.Height) @@ -69,13 +69,5 @@ namespace Avalonia.Win32.Interop.Wpf public Vector Dpi { get; } public PixelFormat Format => PixelFormat.Bgra8888; } - - Vector GetScaling() - { - var src = PresentationSource.FromVisual(_impl)?.CompositionTarget; - if (src == null) - return new Vector(1, 1); - return new Vector(src.TransformToDevice.M11, src.TransformToDevice.M22); - } } } From 1cc13484c020190c5c03ede643b1c8defc6dade6 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2017 04:32:01 +0300 Subject: [PATCH 03/11] Cleanup --- .../Wpf/Direct2DImageSurface.cs | 51 +++++++++---------- .../Wpf/WpfAvaloniaHost.cs | 20 +++++++- .../Wpf/WpfTopLevelImpl.cs | 7 ++- 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs index 303e0850aa..57efe700dd 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs @@ -24,17 +24,18 @@ using Usage = SharpDX.Direct3D9.Usage; namespace Avalonia.Win32.Interop.Wpf { - class Direct2DImageSurface : IExternalDirect2DRenderTargetSurface + class Direct2DImageSurface : IExternalDirect2DRenderTargetSurface, IDisposable { - class Pair: IDisposable + class SwapBuffer: IDisposable { + + private readonly SharpDX.Direct3D11.Resource _resource; + private readonly SharpDX.Direct3D11.Resource _stagingResource; public SharpDX.Direct3D9.Surface Texture { get; } - public SharpDX.Direct3D11.Resource D3D11Resource { get; } - public SharpDX.Direct3D11.Resource StagingResource { get; } public RenderTarget Target { get;} public Size Size { get; } - public Pair(Size size, Vector dpi) + public SwapBuffer(Size size, Vector dpi) { int width = (int) size.Width; int height = (int) size.Height; @@ -53,7 +54,7 @@ namespace Avalonia.Win32.Interop.Wpf using (var surface = texture.QueryInterface()) using (var resource = texture.QueryInterface()) { - D3D11Resource = texture.QueryInterface(); + _resource = texture.QueryInterface(); var handle = resource.SharedHandle; using (var texture9 = new Texture(s_d3DDevice, texture.Description.Width, texture.Description.Height, 1, @@ -80,7 +81,7 @@ namespace Avalonia.Win32.Interop.Wpf SampleDescription = new SampleDescription(1, 0), CpuAccessFlags = CpuAccessFlags.Read })) - StagingResource = texture.QueryInterface(); + _stagingResource = texture.QueryInterface(); Size = size; } @@ -88,24 +89,22 @@ namespace Avalonia.Win32.Interop.Wpf { Texture?.Dispose(); Target?.Dispose(); - D3D11Resource?.Dispose(); - StagingResource?.Dispose(); + _resource?.Dispose(); + _stagingResource?.Dispose(); } public void Flush() { - - s_dxDevice.ImmediateContext.CopySubresourceRegion(D3D11Resource, 0, - new ResourceRegion(0, 0, 0, 1, 1, 1), StagingResource, 0, 0, 0, 0); - s_dxDevice.ImmediateContext.MapSubresource(StagingResource, 0, MapMode.Read, MapFlags.None); - s_dxDevice.ImmediateContext.UnmapSubresource(StagingResource, 0); - + s_dxDevice.ImmediateContext.CopySubresourceRegion(_resource, 0, + new ResourceRegion(0, 0, 0, 1, 1, 1), _stagingResource, 0, 0, 0, 0); + s_dxDevice.ImmediateContext.MapSubresource(_stagingResource, 0, MapMode.Read, MapFlags.None); + s_dxDevice.ImmediateContext.UnmapSubresource(_stagingResource, 0); } } private D3DImage _image; - private Pair _backBuffer; - private Pair _frontBuffer; + private SwapBuffer _backBuffer; + private SwapBuffer _frontBuffer; private readonly WpfTopLevelImpl _impl; private static Device s_dxDevice; private static Direct3DEx s_d3DContext; @@ -149,11 +148,9 @@ namespace Avalonia.Win32.Interop.Wpf return _backBuffer.Target; if (_image == null) - _image = new DX11Image(); + _image = new D3DImage(); _impl.ImageSource = _image; - - RemoveAndDispose(ref _backBuffer); if (size == default(Size)) { @@ -163,7 +160,7 @@ namespace Avalonia.Win32.Interop.Wpf _image.Unlock(); return null; } - _backBuffer = new Pair(size, dpi); + _backBuffer = new SwapBuffer(size, dpi); return _backBuffer.Target; } @@ -174,11 +171,6 @@ namespace Avalonia.Win32.Interop.Wpf d = default(T); } - void DoSwap() - { - - } - void Swap() { var oldFront = _frontBuffer; @@ -193,6 +185,8 @@ namespace Avalonia.Win32.Interop.Wpf public void DestroyRenderTarget() { + RemoveAndDispose(ref _backBuffer); + RemoveAndDispose(ref _frontBuffer); //? } @@ -202,5 +196,10 @@ namespace Avalonia.Win32.Interop.Wpf } public void AfterDrawing() => Swap(); + public void Dispose() + { + RemoveAndDispose(ref _frontBuffer); + RemoveAndDispose(ref _backBuffer); + } } } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs index e36b53199a..0a15bc26d2 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs @@ -21,15 +21,31 @@ namespace Avalonia.Win32.Interop.Wpf { private WpfTopLevelImpl _impl; private readonly SynchronizationContext _sync; + private bool _hasChildren; public WpfAvaloniaHost() { _sync = SynchronizationContext.Current; _impl = new WpfTopLevelImpl(); _impl.ControlRoot.Prepare(); _impl.Visibility = Visibility.Visible; - AddLogicalChild(_impl); - AddVisualChild(_impl); SnapsToDevicePixels = true; + PresentationSource.AddSourceChangedHandler(this, OnSourceChanged); + } + + private void OnSourceChanged(object sender, SourceChangedEventArgs e) + { + if (e.NewSource != null && !_hasChildren) + { + AddLogicalChild(_impl); + AddVisualChild(_impl); + _hasChildren = true; + } + else + { + RemoveVisualChild(_impl); + RemoveLogicalChild(_impl); + _hasChildren = false; + } } public object Content diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index b5715d43d5..fbed2f621c 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -88,7 +88,12 @@ namespace Avalonia.Win32.Interop.Wpf _ttl.ScalingChanged?.Invoke(_ttl.Scaling); } - public void Dispose() => _ttl.Closed?.Invoke(); + public void Dispose() + { + _ttl.Closed?.Invoke(); + foreach(var d in _surfaces.OfType()) + d.Dispose(); + } Size ITopLevelImpl.ClientSize => _finalSize; IMouseDevice ITopLevelImpl.MouseDevice => _mouse; From e0f481ae9fcb91aa3d03ef796a87bac4c73e905b Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2017 06:02:23 +0300 Subject: [PATCH 04/11] Move data between two Texture2D instances manually --- .../Wpf/Direct2DImageSurface.cs | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs index 57efe700dd..9bb9c014b7 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs @@ -17,6 +17,8 @@ using Device = SharpDX.Direct3D11.Device; using Format = SharpDX.DXGI.Format; using MapFlags = SharpDX.Direct3D11.MapFlags; using PresentParameters = SharpDX.DXGI.PresentParameters; +using Query = SharpDX.Direct3D11.Query; +using QueryType = SharpDX.Direct3D11.QueryType; using RenderTarget = SharpDX.Direct2D1.RenderTarget; using Surface = SharpDX.DXGI.Surface; using SwapEffect = SharpDX.DXGI.SwapEffect; @@ -28,9 +30,9 @@ namespace Avalonia.Win32.Interop.Wpf { class SwapBuffer: IDisposable { - + private Query _event; private readonly SharpDX.Direct3D11.Resource _resource; - private readonly SharpDX.Direct3D11.Resource _stagingResource; + private readonly SharpDX.Direct3D11.Resource _sharedResource; public SharpDX.Direct3D9.Surface Texture { get; } public RenderTarget Target { get;} public Size Size { get; } @@ -39,6 +41,7 @@ namespace Avalonia.Win32.Interop.Wpf { int width = (int) size.Width; int height = (int) size.Height; + _event = new Query(s_dxDevice, new QueryDescription {Type = QueryType.Event}); using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription { Width = width, @@ -47,19 +50,14 @@ namespace Avalonia.Win32.Interop.Wpf MipLevels = 1, Format = Format.B8G8R8A8_UNorm, Usage = ResourceUsage.Default, - SampleDescription = new SampleDescription(1, 0), - BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, - OptionFlags = ResourceOptionFlags.Shared + SampleDescription = new SampleDescription(2, 0), + BindFlags = BindFlags.RenderTarget, })) using (var surface = texture.QueryInterface()) - using (var resource = texture.QueryInterface()) + { _resource = texture.QueryInterface(); - var handle = resource.SharedHandle; - using (var texture9 = new Texture(s_d3DDevice, texture.Description.Width, - texture.Description.Height, 1, - Usage.RenderTarget, SharpDX.Direct3D9.Format.A8R8G8B8, Pool.Default, ref handle)) - Texture = texture9.GetSurfaceLevel(0); + Target = new RenderTarget(AvaloniaLocator.Current.GetService(), surface, new RenderTargetProperties { @@ -72,16 +70,25 @@ namespace Avalonia.Win32.Interop.Wpf } using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription { - Width = Math.Min(width, 16), - Height = Math.Min(height, 16), + Width = width, + Height = height, ArraySize = 1, MipLevels = 1, Format = Format.B8G8R8A8_UNorm, - Usage = ResourceUsage.Staging, + Usage = ResourceUsage.Default, SampleDescription = new SampleDescription(1, 0), - CpuAccessFlags = CpuAccessFlags.Read + BindFlags = BindFlags.RenderTarget|BindFlags.ShaderResource, + OptionFlags = ResourceOptionFlags.Shared, })) - _stagingResource = texture.QueryInterface(); + using (var resource = texture.QueryInterface()) + { + _sharedResource = texture.QueryInterface(); + var handle = resource.SharedHandle; + using (var texture9 = new Texture(s_d3DDevice, texture.Description.Width, + texture.Description.Height, 1, + Usage.RenderTarget, SharpDX.Direct3D9.Format.A8R8G8B8, Pool.Default, ref handle)) + Texture = texture9.GetSurfaceLevel(0); + } Size = size; } @@ -90,21 +97,20 @@ namespace Avalonia.Win32.Interop.Wpf Texture?.Dispose(); Target?.Dispose(); _resource?.Dispose(); - _stagingResource?.Dispose(); + _sharedResource?.Dispose(); } public void Flush() { - s_dxDevice.ImmediateContext.CopySubresourceRegion(_resource, 0, - new ResourceRegion(0, 0, 0, 1, 1, 1), _stagingResource, 0, 0, 0, 0); - s_dxDevice.ImmediateContext.MapSubresource(_stagingResource, 0, MapMode.Read, MapFlags.None); - s_dxDevice.ImmediateContext.UnmapSubresource(_stagingResource, 0); + s_dxDevice.ImmediateContext.ResolveSubresource(_resource, 0, _sharedResource, 0, Format.B8G8R8A8_UNorm); + s_dxDevice.ImmediateContext.Flush(); + s_dxDevice.ImmediateContext.End(_event); + s_dxDevice.ImmediateContext.GetData(_event).Dispose(); } } private D3DImage _image; private SwapBuffer _backBuffer; - private SwapBuffer _frontBuffer; private readonly WpfTopLevelImpl _impl; private static Device s_dxDevice; private static Direct3DEx s_d3DContext; @@ -154,7 +160,6 @@ namespace Avalonia.Win32.Interop.Wpf RemoveAndDispose(ref _backBuffer); if (size == default(Size)) { - RemoveAndDispose(ref _frontBuffer); _image.Lock(); _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); _image.Unlock(); @@ -173,12 +178,9 @@ namespace Avalonia.Win32.Interop.Wpf void Swap() { - var oldFront = _frontBuffer; - _frontBuffer = _backBuffer; - _backBuffer = oldFront; - _frontBuffer.Flush(); + _backBuffer.Flush(); _image.Lock(); - _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _frontBuffer?.Texture?.NativePointer ?? IntPtr.Zero, true); + _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _backBuffer?.Texture?.NativePointer ?? IntPtr.Zero, true); _image.AddDirtyRect(new Int32Rect(0, 0, _image.PixelWidth, _image.PixelHeight)); _image.Unlock(); } @@ -186,8 +188,6 @@ namespace Avalonia.Win32.Interop.Wpf public void DestroyRenderTarget() { RemoveAndDispose(ref _backBuffer); - RemoveAndDispose(ref _frontBuffer); - //? } public void BeforeDrawing() @@ -198,7 +198,6 @@ namespace Avalonia.Win32.Interop.Wpf public void AfterDrawing() => Swap(); public void Dispose() { - RemoveAndDispose(ref _frontBuffer); RemoveAndDispose(ref _backBuffer); } } From 714869033c8bcd96932ea32308894a33901a0ec4 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2017 12:06:04 +0300 Subject: [PATCH 05/11] Reference SharpDX.Direct3D9 package --- packages.cake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages.cake b/packages.cake index bc1aeef416..46fa26ee4b 100644 --- a/packages.cake +++ b/packages.cake @@ -80,6 +80,7 @@ public class Packages var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1; var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1; var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1; + var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1; var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1; context.Information("Package: Serilog, version: {0}", SerilogVersion); @@ -91,6 +92,7 @@ public class Packages context.Information("Package: SharpDX, version: {0}", SharpDXVersion); context.Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version); context.Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version); + context.Information("Package: SharpDX.Direct3D9, version: {0}", SharpDXDirect3D9Version); context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion); var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME") @@ -472,6 +474,7 @@ public class Packages { new NuSpecDependency() { Id = "Avalonia.Win32", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = parameters.Version }, + new NuSpecDependency() { Id = "SharpDX.Direct3D9", Version = SharpDXDirect3D9Version }, }, Files = new [] { From 099a7ae752a1f48e292785a0af4459103e67c735 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2017 12:23:00 +0300 Subject: [PATCH 06/11] Dispose event --- src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs index 9bb9c014b7..8891a76676 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs @@ -30,7 +30,7 @@ namespace Avalonia.Win32.Interop.Wpf { class SwapBuffer: IDisposable { - private Query _event; + private readonly Query _event; private readonly SharpDX.Direct3D11.Resource _resource; private readonly SharpDX.Direct3D11.Resource _sharedResource; public SharpDX.Direct3D9.Surface Texture { get; } @@ -98,6 +98,7 @@ namespace Avalonia.Win32.Interop.Wpf Target?.Dispose(); _resource?.Dispose(); _sharedResource?.Dispose(); + _event?.Dispose(); } public void Flush() From d5806d1af2bd05130691b4705a38235955e7b09d Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2017 14:18:31 +0300 Subject: [PATCH 07/11] Fixed DPI support --- .../Avalonia.Win32.Interop.csproj | 1 + .../Wpf/Direct2DImageSurface.cs | 17 +++--- .../Avalonia.Win32.Interop/Wpf/IntSize.cs | 59 +++++++++++++++++++ .../Wpf/WpfAvaloniaHost.cs | 1 + 4 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj index 099a7f4074..5f1a065028 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs index 8891a76676..8fe7275a0f 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs @@ -35,9 +35,9 @@ namespace Avalonia.Win32.Interop.Wpf private readonly SharpDX.Direct3D11.Resource _sharedResource; public SharpDX.Direct3D9.Surface Texture { get; } public RenderTarget Target { get;} - public Size Size { get; } + public IntSize Size { get; } - public SwapBuffer(Size size, Vector dpi) + public SwapBuffer(IntSize size, Vector dpi) { int width = (int) size.Width; int height = (int) size.Height; @@ -116,6 +116,7 @@ namespace Avalonia.Win32.Interop.Wpf private static Device s_dxDevice; private static Direct3DEx s_d3DContext; private static DeviceEx s_d3DDevice; + private Vector _oldDpi; [DllImport("user32.dll", SetLastError = false)] @@ -148,18 +149,20 @@ namespace Avalonia.Win32.Interop.Wpf { EnsureDirectX(); var scale = _impl.GetScaling(); - var size = new Size(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y); + var size = new IntSize(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y); var dpi = scale * 96; if (_backBuffer!=null && _backBuffer.Size == size) return _backBuffer.Target; - - if (_image == null) - _image = new D3DImage(); + + if (_image == null || _oldDpi.X != dpi.X || _oldDpi.Y != dpi.Y) + { + _image = new D3DImage(dpi.X, dpi.Y); + } _impl.ImageSource = _image; RemoveAndDispose(ref _backBuffer); - if (size == default(Size)) + if (size == default(IntSize)) { _image.Lock(); _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs new file mode 100644 index 0000000000..3fdbdedfd9 --- /dev/null +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Avalonia.Win32.Interop.Wpf +{ + struct IntSize : IEquatable + { + public bool Equals(IntSize other) + { + return Width == other.Width && Height == other.Height; + } + + public IntSize(int width, int height) + { + Width = width; + Height = height; + } + + public IntSize(double width, double height) : this((int) width, (int) height) + { + + } + + public static implicit operator IntSize(System.Windows.Size size) + { + return new IntSize {Width = (int) size.Width, Height = (int) size.Height}; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is IntSize && Equals((IntSize) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Width * 397) ^ Height; + } + } + + public static bool operator ==(IntSize left, IntSize right) + { + return left.Equals(right); + } + + public static bool operator !=(IntSize left, IntSize right) + { + return !left.Equals(right); + } + + public int Width { get; set; } + public int Height { get; set; } + } +} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs index 0a15bc26d2..6dc9ba9e09 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs @@ -29,6 +29,7 @@ namespace Avalonia.Win32.Interop.Wpf _impl.ControlRoot.Prepare(); _impl.Visibility = Visibility.Visible; SnapsToDevicePixels = true; + UseLayoutRounding = true; PresentationSource.AddSourceChangedHandler(this, OnSourceChanged); } From 2638f02cd6d7d73cf067fa3c3b6ed8bdf5e23aea Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 18 Jul 2017 09:55:10 +0100 Subject: [PATCH 08/11] fix null reference when focusing textbox in attached to visual tree, but before ontemplate applied. --- src/Avalonia.Controls/TextBox.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index d2e8085d8c..6fc79e5d2c 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -236,6 +236,11 @@ namespace Avalonia.Controls { _presenter = e.NameScope.Get("PART_TextPresenter"); _presenter.Cursor = new Cursor(StandardCursorType.Ibeam); + + if(IsFocused) + { + _presenter.ShowCaret(); + } } protected override void OnGotFocus(GotFocusEventArgs e) @@ -254,7 +259,7 @@ namespace Avalonia.Controls } else { - _presenter.ShowCaret(); + _presenter?.ShowCaret(); } } From c37dd6cda923f65da21aa4a9b6a0a35c30bd431a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 18 Jul 2017 10:02:15 +0100 Subject: [PATCH 09/11] null check on hide caret. --- src/Avalonia.Controls/TextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 6fc79e5d2c..92ab12f82e 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -268,7 +268,7 @@ namespace Avalonia.Controls base.OnLostFocus(e); SelectionStart = 0; SelectionEnd = 0; - _presenter.HideCaret(); + _presenter?.HideCaret(); } protected override void OnTextInput(TextInputEventArgs e) From df61044d50beeabe836d063ee2fae22978bf6f06 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 18 Jul 2017 21:20:14 +0300 Subject: [PATCH 10/11] Fixed text opacity for Skia backend --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 12 +-- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 101 +++++++++---------- 2 files changed, 53 insertions(+), 60 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 4a9f2c6572..3ed0509c0a 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -141,23 +141,17 @@ namespace Avalonia.Skia var rv = new PaintWrapper(paint); paint.IsStroke = false; - // TODO: SkiaSharp does not contain alpha yet! + double opacity = brush.Opacity * _currentOpacity; - //paint.SetAlpha(paint.GetAlpha() * opacity); paint.IsAntialias = true; - SKColor color = new SKColor(255, 255, 255, 255); - var solid = brush as ISolidColorBrush; - if (solid != null) - color = solid.Color.ToSKColor(); - - paint.Color = (new SKColor(color.Red, color.Green, color.Blue, (byte)(color.Alpha * opacity))); - if (solid != null) { + paint.Color = new SKColor(solid.Color.R, solid.Color.G, solid.Color.B, (byte) (solid.Color.A * opacity)); return rv; } + paint.Color = (new SKColor(255, 255, 255, (byte)(255 * opacity))); var gradient = brush as IGradientBrush; if (gradient != null) diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 8568c80c04..1d224f97d7 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -42,7 +42,6 @@ namespace Avalonia.Skia _paint.Typeface = skiaTypeface; _paint.TextSize = (float)(typeface?.FontSize ?? 12); _paint.TextAlign = textAlignment.ToSKTextAlign(); - _paint.BlendMode = SKBlendMode.Src; _wrapping = wrapping; _constraint = constraint; @@ -200,66 +199,65 @@ namespace Avalonia.Skia } ctx->Canvas->restore(); */ - SKPaint paint = _paint; - IDisposable currd = null; - var currentWrapper = foreground; - - try + using (var paint = _paint.Clone()) { - SKPaint currFGPaint = ApplyWrapperTo(ref foreground, ref currd, paint); - bool hasCusomFGBrushes = _foregroundBrushes.Any(); - - for (int c = 0; c < _skiaLines.Count; c++) + IDisposable currd = null; + var currentWrapper = foreground; + SKPaint currentPaint = null; + try { - AvaloniaFormattedTextLine line = _skiaLines[c]; - - float x = TransformX(origin.X, 0, paint.TextAlign); + ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint); + bool hasCusomFGBrushes = _foregroundBrushes.Any(); - if (!hasCusomFGBrushes) - { - var subString = Text.Substring(line.Start, line.Length); - canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint); - } - else + for (int c = 0; c < _skiaLines.Count; c++) { - float currX = x; - string subStr; - int len; + AvaloniaFormattedTextLine line = _skiaLines[c]; - for (int i = line.Start; i < line.Start + line.Length;) - { - var fb = GetNextForegroundBrush(ref line, i, out len); - - if (fb != null) - { - //TODO: figure out how to get the brush size - currentWrapper = context.CreatePaint(fb, new Size()); - } - else - { - if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose(); - currentWrapper = foreground; - } + float x = TransformX(origin.X, 0, paint.TextAlign); - subStr = Text.Substring(i, len); + if (!hasCusomFGBrushes) + { + var subString = Text.Substring(line.Start, line.Length); + canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint); + } + else + { + float currX = x; + string subStr; + int len; - if (currFGPaint != currentWrapper.Paint) + for (int i = line.Start; i < line.Start + line.Length;) { - currFGPaint = ApplyWrapperTo(ref currentWrapper, ref currd, paint); + var fb = GetNextForegroundBrush(ref line, i, out len); + + if (fb != null) + { + //TODO: figure out how to get the brush size + currentWrapper = context.CreatePaint(fb, new Size()); + } + else + { + if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose(); + currentWrapper = foreground; + } + + subStr = Text.Substring(i, len); + + ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint); + + canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); + + i += len; + currX += paint.MeasureText(subStr); } - - canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); - - i += len; - currX += paint.MeasureText(subStr); } } } - } - finally - { - if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose(); - currd?.Dispose(); + finally + { + if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose(); + currd?.Dispose(); + } } } @@ -278,12 +276,13 @@ namespace Avalonia.Skia private Size _size; private List _skiaLines; - private static SKPaint ApplyWrapperTo(ref DrawingContextImpl.PaintWrapper wrapper, + private static void ApplyWrapperTo(ref SKPaint current, DrawingContextImpl.PaintWrapper wrapper, ref IDisposable curr, SKPaint paint) { + if (current == wrapper.Paint) + return; curr?.Dispose(); curr = wrapper.ApplyTo(paint); - return wrapper.Paint; } private static bool IsBreakChar(char c) From 9e35232242f815a68e64d807d92d68d9a3cc2aa8 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 19 Jul 2017 12:23:05 +0300 Subject: [PATCH 11/11] Pick nuget api address from environment --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 6b63176a89..529cbbb65f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,6 +15,7 @@ environment: MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package init: - ps: (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/appveyor/ci/master/scripts/xamarin-vs2017-151-fixed.targets', "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Microsoft.Common.Targets\ImportAfter\Xamarin.Common.targets") +- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")} install: - if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi - if not exist dotnet-1.0.1.exe appveyor DownloadFile https://go.microsoft.com/fwlink/?linkid=843448 -FileName "dotnet-1.0.1.exe"