Browse Source

allow window to clear focus manager when it closes, preventing memory leak.

pull/6811/head
Dan Walmsley 5 years ago
parent
commit
1a8cb9bba9
  1. 6
      src/Avalonia.Controls/WindowBase.cs
  2. 3
      src/Avalonia.Input/ApiCompatBaseline.txt
  3. 18
      src/Avalonia.Input/FocusManager.cs
  4. 8
      src/Avalonia.Input/IFocusManager.cs

6
src/Avalonia.Controls/WindowBase.cs

@ -193,6 +193,12 @@ namespace Avalonia.Controls
try
{
IsVisible = false;
if (this is IFocusScope scope)
{
FocusManager.Instance?.RemoveFocusScope(scope);
}
base.HandleClosed();
}
finally

3
src/Avalonia.Input/ApiCompatBaseline.txt

@ -3,6 +3,7 @@ MembersMustExist : Member 'public Avalonia.Platform.IPlatformHandle Avalonia.Inp
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.RightTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.TappedEvent' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.IFocusManager.ClearFocusScope(Avalonia.Input.IFocusScope)' is present in the implementation but not in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.InputElement.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.InputElement.TappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_DoubleTapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
@ -10,4 +11,4 @@ MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_Tapped(Sy
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_DoubleTapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_Tapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'Avalonia.Platform.IStandardCursorFactory' does not exist in the implementation but it does exist in the contract.
Total Issues: 11
Total Issues: 12

18
src/Avalonia.Input/FocusManager.cs

@ -145,7 +145,7 @@ namespace Avalonia.Input
/// Notifies the focus manager of a change in focus scope.
/// </summary>
/// <param name="scope">The new focus scope.</param>
public void SetFocusScope(IFocusScope scope)
public void SetFocusScope(IFocusScope? scope)
{
scope = scope ?? throw new ArgumentNullException(nameof(scope));
@ -162,6 +162,22 @@ namespace Avalonia.Input
Focus(e);
}
public void RemoveFocusScope(IFocusScope scope)
{
scope = scope ?? throw new ArgumentNullException(nameof(scope));
if (_focusScopes.TryGetValue(scope, out var e))
{
SetFocusedElement(scope, null);
_focusScopes.Remove(scope);
}
if (Scope == scope)
{
Scope = null;
}
}
public static bool GetIsFocusScope(IInputElement e) => e is IFocusScope;
/// <summary>

8
src/Avalonia.Input/IFocusManager.cs

@ -35,5 +35,13 @@ namespace Avalonia.Input
/// when it activates, e.g. when a Window is activated.
/// </remarks>
void SetFocusScope(IFocusScope scope);
/// <summary>
/// Notifies the focus manager that a focus scope has been removed.
/// </summary>
/// <param name="scope">The focus scope to be removed.</param>
/// This should not be called by client code. It is called by an <see cref="IFocusScope"/>
/// when it deactivates or closes, e.g. when a Window is closed.
void RemoveFocusScope(IFocusScope scope);
}
}

Loading…
Cancel
Save