Browse Source

Merge branch 'master' into pr-template

pull/2251/head
Jumar Macato 7 years ago
committed by GitHub
parent
commit
5f6b77e120
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      readme.md
  2. 12
      src/Avalonia.Controls/TopLevel.cs
  3. 2
      src/Avalonia.Input/IPointerDevice.cs
  4. 51
      src/Avalonia.Input/MouseDevice.cs
  5. 26
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  6. 13
      src/Avalonia.Visuals/Rendering/IRenderer.cs
  7. 5
      src/Avalonia.Visuals/Rendering/ImmediateRenderer.cs
  8. 4
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  9. 36
      src/Avalonia.Visuals/Rendering/SceneInvalidatedEventArgs.cs
  10. 1
      tests/Avalonia.LeakTests/ControlTests.cs

6
readme.md

@ -2,9 +2,9 @@
# Avalonia
| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective |
|---|---|---|
| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) |
| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective | NuGet | MyGet |
|---|---|---|---|---|
| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | [![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) | [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) |
## About

12
src/Avalonia.Controls/TopLevel.cs

@ -98,6 +98,11 @@ namespace Avalonia.Controls
Renderer = impl.CreateRenderer(this);
if (Renderer != null)
{
Renderer.SceneInvalidated += SceneInvalidated;
}
impl.SetInputRoot(this);
impl.Closed = HandleClosed;
@ -231,7 +236,7 @@ namespace Avalonia.Controls
{
PlatformImpl?.Invalidate(rect);
}
/// <inheritdoc/>
Point IRenderRoot.PointToClient(PixelPoint p)
{
@ -349,5 +354,10 @@ namespace Avalonia.Controls
{
_inputManager.ProcessInput(e);
}
private void SceneInvalidated(object sender, SceneInvalidatedEventArgs e)
{
(this as IInputRoot).MouseDevice.SceneInvalidated(this, e.DirtyRect);
}
}
}

2
src/Avalonia.Input/IPointerDevice.cs

@ -12,5 +12,7 @@ namespace Avalonia.Input
void Capture(IInputElement control);
Point GetPosition(IVisual relativeTo);
void SceneInvalidated(IInputRoot root, Rect rect);
}
}

51
src/Avalonia.Input/MouseDevice.cs

@ -104,6 +104,23 @@ namespace Avalonia.Input
ProcessRawEvent(margs);
}
public void SceneInvalidated(IInputRoot root, Rect rect)
{
var clientPoint = root.PointToClient(Position);
if (rect.Contains(clientPoint))
{
if (Captured == null)
{
SetPointerOver(this, root, clientPoint);
}
else
{
SetPointerOver(this, root, Captured);
}
}
}
private void ProcessRawEvent(RawMouseEventArgs e)
{
Contract.Requires<ArgumentNullException>(e != null);
@ -305,16 +322,41 @@ namespace Avalonia.Input
Device = device,
};
if (element!=null && !element.IsAttachedToVisualTree)
{
// element has been removed from visual tree so do top down cleanup
if (root.IsPointerOver)
ClearChildrenPointerOver(e, root,true);
}
while (element != null)
{
e.Source = element;
e.Handled = false;
element.RaiseEvent(e);
element = (IInputElement)element.VisualParent;
}
root.PointerOverElement = null;
}
private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element,bool clearRoot)
{
foreach (IInputElement el in element.VisualChildren)
{
if (el.IsPointerOver)
{
ClearChildrenPointerOver(e, el, true);
break;
}
}
if(clearRoot)
{
e.Source = element;
e.Handled = false;
element.RaiseEvent(e);
}
}
private IInputElement SetPointerOver(IPointerDevice device, IInputRoot root, Point p)
{
Contract.Requires<ArgumentNullException>(device != null);
@ -361,13 +403,18 @@ namespace Avalonia.Input
el = root.PointerOverElement;
e.RoutedEvent = InputElement.PointerLeaveEvent;
if (el!=null && branch!=null && !el.IsAttachedToVisualTree)
{
ClearChildrenPointerOver(e,branch,false);
}
while (el != null && el != branch)
{
e.Source = el;
e.Handled = false;
el.RaiseEvent(e);
el = (IInputElement)el.VisualParent;
}
}
el = root.PointerOverElement = element;
e.RoutedEvent = InputElement.PointerEnterEvent;

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

@ -29,6 +29,7 @@ namespace Avalonia.Rendering
private readonly ISceneBuilder _sceneBuilder;
private bool _running;
private bool _disposed;
private volatile IRef<Scene> _scene;
private DirtyVisuals _dirty;
private IRef<IRenderTargetBitmapImpl> _overlay;
@ -99,6 +100,9 @@ namespace Avalonia.Rendering
/// </summary>
public string DebugFramesPath { get; set; }
/// <inheritdoc/>
public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
/// <summary>
/// Gets the render layers.
/// </summary>
@ -122,6 +126,9 @@ namespace Avalonia.Rendering
{
lock (_sceneLock)
{
if (_disposed)
return;
_disposed = true;
var scene = _scene;
_scene = null;
scene?.Dispose();
@ -168,7 +175,7 @@ namespace Avalonia.Rendering
var t = (IRenderLoopTask)this;
if(t.NeedsUpdate)
UpdateScene();
if(_scene.Item != null)
if(_scene?.Item != null)
Render(true);
}
@ -478,6 +485,8 @@ namespace Avalonia.Rendering
Dispatcher.UIThread.VerifyAccess();
lock (_sceneLock)
{
if (_disposed)
return;
if (_scene?.Item.Generation > _lastSceneId)
return;
}
@ -506,6 +515,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

13
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
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/>

4
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@ -160,7 +160,7 @@ namespace Avalonia.Rendering.SceneGraph
private IEnumerable<IVisual> HitTest(IVisualNode node, Point p, Rect? clip, Func<IVisual, bool> filter)
{
if (filter?.Invoke(node.Visual) != false)
if (filter?.Invoke(node.Visual) != false && node.Visual.IsAttachedToVisualTree)
{
var clipped = false;
@ -186,7 +186,7 @@ namespace Avalonia.Rendering.SceneGraph
}
}
if (node.HitTest(p) && node.Visual.IsAttachedToVisualTree)
if (node.HitTest(p))
{
yield return node.Visual;
}

36
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
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)
{

Loading…
Cancel
Save