浏览代码

Added IRenderer.SceneInvalidated event.

And use this event to trigger an update of the mouse pointer-over state.
Steven Kirk 6 年之前
父节点
当前提交
38a3db18cb

+ 3 - 3
src/Avalonia.Controls/TopLevel.cs

@@ -97,6 +97,7 @@ namespace Avalonia.Controls
             _renderInterface = TryGetService<IPlatformRenderInterface>(dependencyResolver);
 
             Renderer = impl.CreateRenderer(this);
+            Renderer.SceneInvalidated += SceneInvalidated;
 
             impl.SetInputRoot(this);
 
@@ -230,7 +231,6 @@ namespace Avalonia.Controls
         void IRenderRoot.Invalidate(Rect rect)
         {
             PlatformImpl?.Invalidate(rect);
-            UpdatePointerOver(rect);
         }
         
         /// <inheritdoc/>
@@ -351,9 +351,9 @@ namespace Avalonia.Controls
             _inputManager.ProcessInput(e);
         }
 
-        private void UpdatePointerOver(Rect rect)
+        private void SceneInvalidated(object sender, SceneInvalidatedEventArgs e)
         {
-            (this as IInputRoot).MouseDevice.SceneInvalidated(this, rect);
+            (this as IInputRoot).MouseDevice.SceneInvalidated(this, e.DirtyRect);
         }
     }
 }

+ 18 - 0
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -99,6 +99,9 @@ namespace Avalonia.Rendering
         /// </summary>
         public string DebugFramesPath { get; set; }
 
+        /// <inheritdoc/>
+        public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
+
         /// <summary>
         /// Gets the render layers.
         /// </summary>
@@ -470,6 +473,21 @@ namespace Avalonia.Rendering
                     oldScene?.Dispose();
                 }
 
+                if (SceneInvalidated != null)
+                {
+                    var rect = new Rect();
+
+                    foreach (var layer in scene.Layers)
+                    {
+                        foreach (var dirty in layer.Dirty)
+                        {
+                            rect = rect.Union(dirty);
+                        }
+                    }
+
+                    SceneInvalidated(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
+                }
+
                 _dirty.Clear();
             }
             else

+ 11 - 2
src/Avalonia.Visuals/Rendering/IRenderer.cs

@@ -18,11 +18,20 @@ namespace Avalonia.Rendering
         bool DrawFps { get; set; }
 
         /// <summary>
-        /// Gets or sets a value indicating whether the renderer should a visual representation
+        /// Gets or sets a value indicating whether the renderer should draw a visual representation
         /// of its dirty rectangles.
         /// </summary>
         bool DrawDirtyRects { get; set; }
 
+        /// <summary>
+        /// Raised when a portion of the scene has been invalidated.
+        /// </summary>
+        /// <remarks>
+        /// Indicates that the underlying low-level scene information has been updated. Used to
+        /// signal that an update to the current pointer-over state may be required.
+        /// </remarks>
+        event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
+
         /// <summary>
         /// Mark a visual as dirty and needing re-rendering.
         /// </summary>
@@ -63,4 +72,4 @@ namespace Avalonia.Rendering
         /// </summary>
         void Stop();
     }
-}
+}

+ 5 - 0
src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs

@@ -42,6 +42,9 @@ namespace Avalonia.Rendering
         /// <inheritdoc/>
         public bool DrawDirtyRects { get; set; }
 
+        /// <inheritdoc/>
+        public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
+
         /// <inheritdoc/>
         public void Paint(Rect rect)
         {
@@ -81,6 +84,8 @@ namespace Avalonia.Rendering
                 _renderTarget.Dispose();
                 _renderTarget = null;
             }
+
+            SceneInvalidated?.Invoke(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
         }
 
         /// <inheritdoc/>

+ 36 - 0
src/Avalonia.Visuals/Rendering/SceneInvalidatedEventArgs.cs

@@ -0,0 +1,36 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+
+namespace Avalonia.Rendering
+{
+    /// <summary>
+    /// Provides data for the <see cref="IRenderer.SceneInvalidated"/> event.
+    /// </summary>
+    public class SceneInvalidatedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SceneInvalidatedEventArgs"/> class.
+        /// </summary>
+        /// <param name="root">The render root that has been updated.</param>
+        /// <param name="dirtyRect">The updated area.</param>
+        public SceneInvalidatedEventArgs(
+            IRenderRoot root,
+            Rect dirtyRect)
+        {
+            RenderRoot = root;
+            DirtyRect = dirtyRect;
+        }
+
+        /// <summary>
+        /// Gets the invalidated area.
+        /// </summary>
+        public Rect DirtyRect { get; }
+
+        /// <summary>
+        /// Gets the render root that has been invalidated.
+        /// </summary>
+        public IRenderRoot RenderRoot { get; }
+    }
+}

+ 1 - 0
tests/Avalonia.LeakTests/ControlTests.cs

@@ -348,6 +348,7 @@ namespace Avalonia.LeakTests
         {
             public bool DrawFps { get; set; }
             public bool DrawDirtyRects { get; set; }
+            public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
 
             public void AddDirty(IVisual visual)
             {