diff --git a/.ncrunch/Avalonia.LinuxFramebuffer.v3.ncrunchproject b/.ncrunch/Avalonia.LinuxFramebuffer.v3.ncrunchproject new file mode 100644 index 0000000000..6800b4a3fe --- /dev/null +++ b/.ncrunch/Avalonia.LinuxFramebuffer.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/Avalonia.Visuals.UnitTests.net461.v3.ncrunchproject b/.ncrunch/Avalonia.Visuals.UnitTests.net461.v3.ncrunchproject new file mode 100644 index 0000000000..6800b4a3fe --- /dev/null +++ b/.ncrunch/Avalonia.Visuals.UnitTests.net461.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/Avalonia.Win32.Interop.v3.ncrunchproject b/.ncrunch/Avalonia.Win32.Interop.v3.ncrunchproject new file mode 100644 index 0000000000..6800b4a3fe --- /dev/null +++ b/.ncrunch/Avalonia.Win32.Interop.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/build.cake b/build.cake index c56089ab55..6c2e554df4 100644 --- a/build.cake +++ b/build.cake @@ -193,7 +193,7 @@ Task("Run-Net-Core-Unit-Tests") Task("Run-Unit-Tests") .IsDependentOn("Run-Net-Core-Unit-Tests") .IsDependentOn("Build") - .IsDependentOn("Run-Leak-Tests") + //.IsDependentOn("Run-Leak-Tests") .WithCriteria(() => !parameters.SkipTests) .Does(() => { diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs index c7c61e2b4e..413794dfa2 100644 --- a/samples/ControlCatalog/MainWindow.xaml.cs +++ b/samples/ControlCatalog/MainWindow.xaml.cs @@ -10,6 +10,7 @@ namespace ControlCatalog { this.InitializeComponent(); this.AttachDevTools(); + Renderer.DrawDirtyRects = Renderer.DrawFps = true; } private void InitializeComponent() diff --git a/samples/interop/Direct3DInteropSample/Program.cs b/samples/interop/Direct3DInteropSample/Program.cs index 7fb650a7a8..d5de5ccb4e 100644 --- a/samples/interop/Direct3DInteropSample/Program.cs +++ b/samples/interop/Direct3DInteropSample/Program.cs @@ -11,7 +11,7 @@ namespace Direct3DInteropSample { static void Main(string[] args) { - AppBuilder.Configure().UseWin32().UseDirect2D1().Start(); + AppBuilder.Configure().UseWin32(deferredRendering: false).UseDirect2D1().Start(); } } } diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index e9b4ad0a6d..7134e7d1b4 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -52,13 +52,11 @@ namespace Avalonia.Android .Bind().ToTransient() .Bind().ToSingleton() .Bind().ToConstant(Instance) - .Bind().ToConstant(ImmediateRenderer.Factory) .Bind().ToConstant(new AndroidThreadingInterface()) .Bind().ToTransient() .Bind().ToConstant(Instance) .Bind().ToSingleton() .Bind().ToConstant(new DefaultRenderLoop(60)) - .Bind().ToConstant(new AssetLoader(app.GetType().Assembly)); SkiaPlatform.Initialize(); diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 0c62eb9060..6c8db17c71 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -13,6 +13,7 @@ using System.Reactive.Disposables; using Avalonia.Android.Platform.Input; using Avalonia.Controls; using Avalonia.Controls.Platform.Surfaces; +using Avalonia.Rendering; namespace Avalonia.Android.Platform.SkiaPlatform { @@ -85,7 +86,12 @@ namespace Avalonia.Android.Platform.SkiaPlatform public IPlatformHandle Handle => _view; public IEnumerable Surfaces => new object[] {this}; - + + public IRenderer CreateRenderer(IRenderRoot root) + { + return new ImmediateRenderer(root); + } + public virtual void Hide() { _view.Visibility = ViewStates.Invisible; diff --git a/src/Avalonia.Base/Utilities/WeakObservable.cs b/src/Avalonia.Base/Utilities/WeakObservable.cs index c261cc0520..b1fe78c206 100644 --- a/src/Avalonia.Base/Utilities/WeakObservable.cs +++ b/src/Avalonia.Base/Utilities/WeakObservable.cs @@ -16,12 +16,13 @@ namespace Avalonia.Utilities /// Converts a .NET event conforming to the standard .NET event pattern into an observable /// sequence, subscribing weakly. /// + /// The type of target. /// The type of the event args. /// Object instance that exposes the event to convert. /// Name of the event to convert. /// - public static IObservable> FromEventPattern( - object target, + public static IObservable> FromEventPattern( + TTarget target, string eventName) where TEventArgs : EventArgs { diff --git a/src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs b/src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs index 356be2ba31..f1e8fa6f9b 100644 --- a/src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs +++ b/src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs @@ -17,22 +17,23 @@ namespace Avalonia.Utilities /// /// Subscribes to an event on an object using a weak subscription. /// - /// The type of the event arguments. + /// The type of the target. + /// The type of the event arguments. /// The event source. /// The name of the event. /// The subscriber. - public static void Subscribe(object target, string eventName, IWeakSubscriber subscriber) - where T : EventArgs + public static void Subscribe(TTarget target, string eventName, IWeakSubscriber subscriber) + where TEventArgs : EventArgs { - var dic = SubscriptionTypeStorage.Subscribers.GetOrCreateValue(target); - Subscription sub; + var dic = SubscriptionTypeStorage.Subscribers.GetOrCreateValue(target); + Subscription sub; if (!dic.TryGetValue(eventName, out sub)) { - dic[eventName] = sub = new Subscription(dic, target, eventName); + dic[eventName] = sub = new Subscription(dic, typeof(TTarget), target, eventName); } - sub.Add(new WeakReference>(subscriber)); + sub.Add(new WeakReference>(subscriber)); } /// @@ -84,19 +85,18 @@ namespace Avalonia.Utilities private WeakReference>[] _data = new WeakReference>[16]; private int _count = 0; - public Subscription(SubscriptionDic sdic, object target, string eventName) + public Subscription(SubscriptionDic sdic, Type targetType, object target, string eventName) { _sdic = sdic; _target = target; _eventName = eventName; - var t = target.GetType(); Dictionary evDic; - if (!Accessors.TryGetValue(t, out evDic)) - Accessors[t] = evDic = new Dictionary(); + if (!Accessors.TryGetValue(targetType, out evDic)) + Accessors[targetType] = evDic = new Dictionary(); if (!evDic.TryGetValue(eventName, out _info)) { - var ev = t.GetRuntimeEvents().FirstOrDefault(x => x.Name == eventName); + var ev = targetType.GetRuntimeEvents().FirstOrDefault(x => x.Name == eventName); if (ev == null) { diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index ba3ecb99c5..60e25d2be6 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.Rendering; using JetBrains.Annotations; namespace Avalonia.Platform @@ -60,6 +61,12 @@ namespace Avalonia.Platform /// Action ScalingChanged { get; set; } + /// + /// Creates a new renderer for the toplevel. + /// + /// The toplevel. + IRenderer CreateRenderer(IRenderRoot root); + /// /// Invalidates a rect on the toplevel. /// diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index a0a8f6b27e..f8db0e2a5b 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -90,8 +90,7 @@ namespace Avalonia.Controls _renderInterface = TryGetService(dependencyResolver); var renderLoop = TryGetService(dependencyResolver); - var rendererFactory = TryGetService(dependencyResolver); - Renderer = rendererFactory?.CreateRenderer(this, renderLoop); + Renderer = impl.CreateRenderer(this); impl.SetInputRoot(this); @@ -181,6 +180,9 @@ namespace Avalonia.Controls /// double ILayoutRoot.LayoutScaling => PlatformImpl?.Scaling ?? 1; + /// + double IRenderRoot.RenderScaling => PlatformImpl?.Scaling ?? 1; + IStyleHost IStyleHost.StylingParent { get { return AvaloniaLocator.Current.GetService(); } diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 3802f2b6ea..46c625cc4c 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -225,8 +225,14 @@ namespace Avalonia.Controls /// public override void Hide() { + if (!IsVisible) + { + return; + } + using (BeginAutoSizing()) { + Renderer?.Stop(); PlatformImpl?.Hide(); } @@ -252,6 +258,7 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { PlatformImpl?.Show(); + Renderer?.Start(); } } @@ -297,6 +304,8 @@ namespace Avalonia.Controls var modal = PlatformImpl?.ShowDialog(); var result = new TaskCompletionSource(); + Renderer?.Start(); + Observable.FromEventPattern( x => this.Closed += x, x => this.Closed -= x) diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index fbdf64b14a..bcc09936ba 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -117,6 +117,7 @@ namespace Avalonia.Controls try { + Renderer?.Stop(); PlatformImpl?.Hide(); IsVisible = false; } @@ -145,6 +146,7 @@ namespace Avalonia.Controls } PlatformImpl?.Show(); + Renderer?.Start(); } finally { diff --git a/src/Avalonia.Themes.Default/CheckBox.xaml b/src/Avalonia.Themes.Default/CheckBox.xaml index e88e93eac6..2fc19b2679 100644 --- a/src/Avalonia.Themes.Default/CheckBox.xaml +++ b/src/Avalonia.Themes.Default/CheckBox.xaml @@ -1,10 +1,11 @@