Browse Source

Nullable enable Avalonia.Input.

pull/4284/head
Steven Kirk 6 years ago
parent
commit
a42e8cbded
  1. 22
      src/Avalonia.Input/AccessKeyHandler.cs
  2. 2
      src/Avalonia.Input/Avalonia.Input.csproj
  3. 6
      src/Avalonia.Input/DataObject.cs
  4. 6
      src/Avalonia.Input/DragDropDevice.cs
  5. 47
      src/Avalonia.Input/FocusManager.cs
  6. 16
      src/Avalonia.Input/GestureRecognizers/GestureRecognizerCollection.cs
  7. 15
      src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs
  8. 9
      src/Avalonia.Input/Gestures.cs
  9. 2
      src/Avalonia.Input/IAccessKeyHandler.cs
  10. 6
      src/Avalonia.Input/IDataObject.cs
  11. 6
      src/Avalonia.Input/IFocusManager.cs
  12. 2
      src/Avalonia.Input/IInputElement.cs
  13. 4
      src/Avalonia.Input/IInputRoot.cs
  14. 4
      src/Avalonia.Input/IKeyboardDevice.cs
  15. 4
      src/Avalonia.Input/IPointer.cs
  16. 4
      src/Avalonia.Input/IPointerDevice.cs
  17. 8
      src/Avalonia.Input/InputElement.cs
  18. 2
      src/Avalonia.Input/InputExtensions.cs
  19. 2
      src/Avalonia.Input/KeyEventArgs.cs
  20. 8
      src/Avalonia.Input/KeyboardDevice.cs
  21. 13
      src/Avalonia.Input/KeyboardNavigationHandler.cs
  22. 73
      src/Avalonia.Input/MouseDevice.cs
  23. 42
      src/Avalonia.Input/Navigation/TabNavigation.cs
  24. 9
      src/Avalonia.Input/Pointer.cs
  25. 14
      src/Avalonia.Input/PointerEventArgs.cs
  26. 2
      src/Avalonia.Input/Raw/RawDragEventType.cs
  27. 2
      src/Avalonia.Input/Raw/RawInputEventArgs.cs
  28. 4
      src/Avalonia.Input/TextInputEventArgs.cs

22
src/Avalonia.Input/AccessKeyHandler.cs

@ -28,7 +28,7 @@ namespace Avalonia.Input
/// <summary>
/// The window to which the handler belongs.
/// </summary>
private IInputRoot _owner;
private IInputRoot? _owner;
/// <summary>
/// Whether access keys are currently being shown;
@ -48,17 +48,17 @@ namespace Avalonia.Input
/// <summary>
/// Element to restore following AltKey taking focus.
/// </summary>
private IInputElement _restoreFocusElement;
private IInputElement? _restoreFocusElement;
/// <summary>
/// The window's main menu.
/// </summary>
private IMainMenu _mainMenu;
private IMainMenu? _mainMenu;
/// <summary>
/// Gets or sets the window's main menu.
/// </summary>
public IMainMenu MainMenu
public IMainMenu? MainMenu
{
get => _mainMenu;
set
@ -86,14 +86,12 @@ namespace Avalonia.Input
/// </remarks>
public void SetOwner(IInputRoot owner)
{
Contract.Requires<ArgumentNullException>(owner != null);
if (_owner != null)
{
throw new InvalidOperationException("AccessKeyHandler owner has already been set.");
}
_owner = owner;
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
_owner.AddHandler(InputElement.KeyDownEvent, OnPreviewKeyDown, RoutingStrategies.Tunnel);
_owner.AddHandler(InputElement.KeyDownEvent, OnKeyDown, RoutingStrategies.Bubble);
@ -149,7 +147,7 @@ namespace Avalonia.Input
// When Alt is pressed without a main menu, or with a closed main menu, show
// access key markers in the window (i.e. "_File").
_owner.ShowAccessKeys = _showingAccessKeys = true;
_owner!.ShowAccessKeys = _showingAccessKeys = true;
}
else
{
@ -241,7 +239,7 @@ namespace Avalonia.Input
{
if (_showingAccessKeys)
{
_owner.ShowAccessKeys = false;
_owner!.ShowAccessKeys = false;
}
}
@ -250,13 +248,13 @@ namespace Avalonia.Input
/// </summary>
private void CloseMenu()
{
MainMenu.Close();
_owner.ShowAccessKeys = _showingAccessKeys = false;
MainMenu!.Close();
_owner!.ShowAccessKeys = _showingAccessKeys = false;
}
private void MainMenuClosed(object sender, EventArgs e)
{
_owner.ShowAccessKeys = false;
_owner!.ShowAccessKeys = false;
}
}
}

2
src/Avalonia.Input/Avalonia.Input.csproj

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>Enable</Nullable>
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />

6
src/Avalonia.Input/DataObject.cs

@ -11,7 +11,7 @@ namespace Avalonia.Input
return _items.ContainsKey(dataFormat);
}
public object Get(string dataFormat)
public object? Get(string dataFormat)
{
if (_items.ContainsKey(dataFormat))
return _items[dataFormat];
@ -23,12 +23,12 @@ namespace Avalonia.Input
return _items.Keys;
}
public IEnumerable<string> GetFileNames()
public IEnumerable<string>? GetFileNames()
{
return Get(DataFormats.FileNames) as IEnumerable<string>;
}
public string GetText()
public string? GetText()
{
return Get(DataFormats.Text) as string;
}

6
src/Avalonia.Input/DragDropDevice.cs

@ -9,9 +9,9 @@ namespace Avalonia.Input
{
public static readonly DragDropDevice Instance = new DragDropDevice();
private Interactive _lastTarget = null;
private Interactive? _lastTarget = null;
private Interactive GetTarget(IInputRoot root, Point local)
private Interactive? GetTarget(IInputRoot root, Point local)
{
var target = root.InputHitTest(local)?.GetSelfAndVisualAncestors()?.OfType<Interactive>()?.FirstOrDefault();
if (target != null && DragDrop.GetAllowDrop(target))
@ -19,7 +19,7 @@ namespace Avalonia.Input
return null;
}
private DragDropEffects RaiseDragEvent(Interactive target, IInputRoot inputRoot, Point point, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data, KeyModifiers modifiers)
private DragDropEffects RaiseDragEvent(Interactive? target, IInputRoot inputRoot, Point point, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data, KeyModifiers modifiers)
{
if (target == null)
return DragDropEffects.None;

47
src/Avalonia.Input/FocusManager.cs

@ -15,8 +15,8 @@ namespace Avalonia.Input
/// <summary>
/// The focus scopes in which the focus is currently defined.
/// </summary>
private readonly ConditionalWeakTable<IFocusScope, IInputElement> _focusScopes =
new ConditionalWeakTable<IFocusScope, IInputElement>();
private readonly ConditionalWeakTable<IFocusScope, IInputElement?> _focusScopes =
new ConditionalWeakTable<IFocusScope, IInputElement?>();
/// <summary>
/// Initializes a new instance of the <see cref="FocusManager"/> class.
@ -37,12 +37,12 @@ namespace Avalonia.Input
/// <summary>
/// Gets the currently focused <see cref="IInputElement"/>.
/// </summary>
public IInputElement Current => KeyboardDevice.Instance?.FocusedElement;
public IInputElement? Current => KeyboardDevice.Instance?.FocusedElement;
/// <summary>
/// Gets the current focus scope.
/// </summary>
public IFocusScope Scope
public IFocusScope? Scope
{
get;
private set;
@ -55,7 +55,7 @@ namespace Avalonia.Input
/// <param name="method">The method by which focus was changed.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
public void Focus(
IInputElement control,
IInputElement? control,
NavigationMethod method = NavigationMethod.Unspecified,
KeyModifiers keyModifiers = KeyModifiers.None)
{
@ -75,17 +75,18 @@ namespace Avalonia.Input
// If control is null, set focus to the topmost focus scope.
foreach (var scope in GetFocusScopeAncestors(Current).Reverse().ToList())
{
IInputElement element;
if (_focusScopes.TryGetValue(scope, out element) && element != null)
if (_focusScopes.TryGetValue(scope, out var element) && element != null)
{
Focus(element, method);
return;
}
}
// Couldn't find a focus scope, clear focus.
SetFocusedElement(Scope, null);
if (Scope is object)
{
// Couldn't find a focus scope, clear focus.
SetFocusedElement(Scope, null);
}
}
}
@ -102,13 +103,13 @@ namespace Avalonia.Input
/// </remarks>
public void SetFocusedElement(
IFocusScope scope,
IInputElement element,
IInputElement? element,
NavigationMethod method = NavigationMethod.Unspecified,
KeyModifiers keyModifiers = KeyModifiers.None)
{
Contract.Requires<ArgumentNullException>(scope != null);
scope = scope ?? throw new ArgumentNullException(nameof(scope));
if (_focusScopes.TryGetValue(scope, out IInputElement existingElement))
if (_focusScopes.TryGetValue(scope, out var existingElement))
{
if (element != existingElement)
{
@ -133,11 +134,9 @@ namespace Avalonia.Input
/// <param name="scope">The new focus scope.</param>
public void SetFocusScope(IFocusScope scope)
{
Contract.Requires<ArgumentNullException>(scope != null);
scope = scope ?? throw new ArgumentNullException(nameof(scope));
IInputElement e;
if (!_focusScopes.TryGetValue(scope, out e))
if (!_focusScopes.TryGetValue(scope, out var e))
{
// TODO: Make this do something useful, i.e. select the first focusable
// control, select a control that the user has specified to have default
@ -164,17 +163,19 @@ namespace Avalonia.Input
/// <returns>The focus scopes.</returns>
private static IEnumerable<IFocusScope> GetFocusScopeAncestors(IInputElement control)
{
while (control != null)
IInputElement? c = control;
while (c != null)
{
var scope = control as IFocusScope;
var scope = c as IFocusScope;
if (scope != null && control.VisualRoot?.IsVisible == true)
if (scope != null && c.VisualRoot?.IsVisible == true)
{
yield return scope;
}
control = control.GetVisualParent<IInputElement>() ??
((control as IHostedVisualTreeRoot)?.Host as IInputElement);
c = c.GetVisualParent<IInputElement>() ??
((c as IHostedVisualTreeRoot)?.Host as IInputElement);
}
}
@ -190,7 +191,7 @@ namespace Avalonia.Input
if (sender == e.Source && ev.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
{
IVisual element = ev.Pointer?.Captured ?? e.Source as IInputElement;
IVisual? element = ev.Pointer?.Captured ?? e.Source as IInputElement;
while (element != null)
{

16
src/Avalonia.Input/GestureRecognizers/GestureRecognizerCollection.cs

@ -1,8 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.LogicalTree;
using Avalonia.Styling;
@ -11,8 +9,8 @@ namespace Avalonia.Input.GestureRecognizers
public class GestureRecognizerCollection : IReadOnlyCollection<IGestureRecognizer>, IGestureRecognizerActionsDispatcher
{
private readonly IInputElement _inputElement;
private List<IGestureRecognizer> _recognizers;
private Dictionary<IPointer, IGestureRecognizer> _pointerGrabs;
private List<IGestureRecognizer>? _recognizers;
private Dictionary<IPointer, IGestureRecognizer>? _pointerGrabs;
public GestureRecognizerCollection(IInputElement inputElement)
@ -72,7 +70,7 @@ namespace Avalonia.Input.GestureRecognizers
{
if (_recognizers == null)
return false;
if (_pointerGrabs.TryGetValue(e.Pointer, out var capture))
if (_pointerGrabs!.TryGetValue(e.Pointer, out var capture))
{
capture.PointerReleased(e);
}
@ -90,7 +88,7 @@ namespace Avalonia.Input.GestureRecognizers
{
if (_recognizers == null)
return false;
if (_pointerGrabs.TryGetValue(e.Pointer, out var capture))
if (_pointerGrabs!.TryGetValue(e.Pointer, out var capture))
{
capture.PointerMoved(e);
}
@ -108,7 +106,7 @@ namespace Avalonia.Input.GestureRecognizers
{
if (_recognizers == null)
return;
_pointerGrabs.Remove(e.Pointer);
_pointerGrabs!.Remove(e.Pointer);
foreach (var r in _recognizers)
{
r.PointerCaptureLost(e.Pointer);
@ -118,8 +116,8 @@ namespace Avalonia.Input.GestureRecognizers
void IGestureRecognizerActionsDispatcher.Capture(IPointer pointer, IGestureRecognizer recognizer)
{
pointer.Capture(_inputElement);
_pointerGrabs[pointer] = recognizer;
foreach (var r in _recognizers)
_pointerGrabs![pointer] = recognizer;
foreach (var r in _recognizers!)
{
if (r != recognizer)
r.PointerCaptureLost(pointer);

15
src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -1,6 +1,5 @@
using System;
using System.Diagnostics;
using Avalonia.Interactivity;
using Avalonia.Threading;
namespace Avalonia.Input.GestureRecognizers
@ -11,9 +10,9 @@ namespace Avalonia.Input.GestureRecognizers
{
private bool _scrolling;
private Point _trackedRootPoint;
private IPointer _tracking;
private IInputElement _target;
private IGestureRecognizerActionsDispatcher _actions;
private IPointer? _tracking;
private IInputElement? _target;
private IGestureRecognizerActionsDispatcher? _actions;
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
private int _gestureId;
@ -95,7 +94,7 @@ namespace Avalonia.Input.GestureRecognizers
_scrolling = true;
if (_scrolling)
{
_actions.Capture(e.Pointer, this);
_actions!.Capture(e.Pointer, this);
}
}
@ -110,7 +109,7 @@ namespace Avalonia.Input.GestureRecognizers
_trackedRootPoint = rootPoint;
if (elapsed.TotalSeconds > 0)
_inertia = vector / elapsed.TotalSeconds;
_target.RaiseEvent(new ScrollGestureEventArgs(_gestureId, vector));
_target!.RaiseEvent(new ScrollGestureEventArgs(_gestureId, vector));
e.Handled = true;
}
}
@ -128,7 +127,7 @@ namespace Avalonia.Input.GestureRecognizers
{
_inertia = default;
_scrolling = false;
_target.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId));
_target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId));
_gestureId = 0;
_lastMoveTimestamp = null;
}
@ -165,7 +164,7 @@ namespace Avalonia.Input.GestureRecognizers
var speed = _inertia * Math.Pow(0.15, st.Elapsed.TotalSeconds);
var distance = speed * elapsedSinceLastTick.TotalSeconds;
_target.RaiseEvent(new ScrollGestureEventArgs(_gestureId, distance));
_target!.RaiseEvent(new ScrollGestureEventArgs(_gestureId, distance));

9
src/Avalonia.Input/Gestures.cs

@ -29,7 +29,9 @@ namespace Avalonia.Input
RoutedEvent.Register<ScrollGestureEventArgs>(
"ScrollGestureEnded", RoutingStrategies.Bubble, typeof(Gestures));
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
private static WeakReference<IInteractive> s_lastPress = new WeakReference<IInteractive>(null);
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
static Gestures()
{
@ -69,6 +71,11 @@ namespace Avalonia.Input
private static void PointerPressed(RoutedEventArgs ev)
{
if (ev.Source is null)
{
return;
}
if (ev.Route == RoutingStrategies.Bubble)
{
var e = (PointerPressedEventArgs)ev;
@ -76,7 +83,7 @@ namespace Avalonia.Input
if (e.ClickCount <= 1)
{
s_lastPress = new WeakReference<IInteractive>(e.Source);
s_lastPress = new WeakReference<IInteractive>(ev.Source);
}
else if (s_lastPress != null && e.ClickCount == 2 && e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
{

2
src/Avalonia.Input/IAccessKeyHandler.cs

@ -8,7 +8,7 @@ namespace Avalonia.Input
/// <summary>
/// Gets or sets the window's main menu.
/// </summary>
IMainMenu MainMenu { get; set; }
IMainMenu? MainMenu { get; set; }
/// <summary>
/// Sets the owner of the access key handler.

6
src/Avalonia.Input/IDataObject.cs

@ -23,17 +23,17 @@ namespace Avalonia.Input
/// Returns the dragged text if the DataObject contains any text.
/// <seealso cref="DataFormats.Text"/>
/// </summary>
string GetText();
string? GetText();
/// <summary>
/// Returns a list of filenames if the DataObject contains filenames.
/// <seealso cref="DataFormats.FileNames"/>
/// </summary>
IEnumerable<string> GetFileNames();
IEnumerable<string>? GetFileNames();
/// <summary>
/// Tries to get the data of the given DataFormat.
/// </summary>
object Get(string dataFormat);
object? Get(string dataFormat);
}
}

6
src/Avalonia.Input/IFocusManager.cs

@ -8,12 +8,12 @@ namespace Avalonia.Input
/// <summary>
/// Gets the currently focused <see cref="IInputElement"/>.
/// </summary>
IInputElement Current { get; }
IInputElement? Current { get; }
/// <summary>
/// Gets the current focus scope.
/// </summary>
IFocusScope Scope { get; }
IFocusScope? Scope { get; }
/// <summary>
/// Focuses a control.
@ -22,7 +22,7 @@ namespace Avalonia.Input
/// <param name="method">The method by which focus was changed.</param>
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
void Focus(
IInputElement control,
IInputElement? control,
NavigationMethod method = NavigationMethod.Unspecified,
KeyModifiers keyModifiers = KeyModifiers.None);

2
src/Avalonia.Input/IInputElement.cs

@ -78,7 +78,7 @@ namespace Avalonia.Input
/// <summary>
/// Gets or sets the associated mouse cursor.
/// </summary>
Cursor Cursor { get; }
Cursor? Cursor { get; }
/// <summary>
/// Gets a value indicating whether this control and all its parents are enabled.

4
src/Avalonia.Input/IInputRoot.cs

@ -20,7 +20,7 @@ namespace Avalonia.Input
/// <summary>
/// Gets or sets the input element that the pointer is currently over.
/// </summary>
IInputElement PointerOverElement { get; set; }
IInputElement? PointerOverElement { get; set; }
/// <summary>
/// Gets or sets a value indicating whether access keys are shown in the window.
@ -31,6 +31,6 @@ namespace Avalonia.Input
/// Gets associated mouse device
/// </summary>
[CanBeNull]
IMouseDevice MouseDevice { get; }
IMouseDevice? MouseDevice { get; }
}
}

4
src/Avalonia.Input/IKeyboardDevice.cs

@ -58,10 +58,10 @@ namespace Avalonia.Input
public interface IKeyboardDevice : IInputDevice, INotifyPropertyChanged
{
IInputElement FocusedElement { get; }
IInputElement? FocusedElement { get; }
void SetFocusedElement(
IInputElement element,
IInputElement? element,
NavigationMethod method,
KeyModifiers modifiers);
}

4
src/Avalonia.Input/IPointer.cs

@ -3,8 +3,8 @@ namespace Avalonia.Input
public interface IPointer
{
int Id { get; }
void Capture(IInputElement control);
IInputElement Captured { get; }
void Capture(IInputElement? control);
IInputElement? Captured { get; }
PointerType Type { get; }
bool IsPrimary { get; }

4
src/Avalonia.Input/IPointerDevice.cs

@ -6,10 +6,10 @@ namespace Avalonia.Input
public interface IPointerDevice : IInputDevice
{
[Obsolete("Use IPointer")]
IInputElement Captured { get; }
IInputElement? Captured { get; }
[Obsolete("Use IPointer")]
void Capture(IInputElement control);
void Capture(IInputElement? control);
[Obsolete("Use PointerEventArgs.GetPosition")]
Point GetPosition(IVisual relativeTo);

8
src/Avalonia.Input/InputElement.cs

@ -37,8 +37,8 @@ namespace Avalonia.Input
/// <summary>
/// Gets or sets associated mouse cursor.
/// </summary>
public static readonly StyledProperty<Cursor> CursorProperty =
AvaloniaProperty.Register<InputElement, Cursor>(nameof(Cursor), null, true);
public static readonly StyledProperty<Cursor?> CursorProperty =
AvaloniaProperty.Register<InputElement, Cursor?>(nameof(Cursor), null, true);
/// <summary>
/// Defines the <see cref="IsFocused"/> property.
@ -160,7 +160,7 @@ namespace Avalonia.Input
private bool _isFocused;
private bool _isFocusVisible;
private bool _isPointerOver;
private GestureRecognizerCollection _gestureRecognizers;
private GestureRecognizerCollection? _gestureRecognizers;
/// <summary>
/// Initializes static members of the <see cref="InputElement"/> class.
@ -336,7 +336,7 @@ namespace Avalonia.Input
/// <summary>
/// Gets or sets associated mouse cursor.
/// </summary>
public Cursor Cursor
public Cursor? Cursor
{
get { return GetValue(CursorProperty); }
set { SetValue(CursorProperty, value); }

2
src/Avalonia.Input/InputExtensions.cs

@ -33,7 +33,7 @@ namespace Avalonia.Input
/// <param name="element">The element to test.</param>
/// <param name="p">The point on <paramref name="element"/>.</param>
/// <returns>The topmost <see cref="IInputElement"/> at the specified position.</returns>
public static IInputElement InputHitTest(this IInputElement element, Point p)
public static IInputElement? InputHitTest(this IInputElement element, Point p)
{
Contract.Requires<ArgumentNullException>(element != null);

2
src/Avalonia.Input/KeyEventArgs.cs

@ -5,7 +5,7 @@ namespace Avalonia.Input
{
public class KeyEventArgs : RoutedEventArgs
{
public IKeyboardDevice Device { get; set; }
public IKeyboardDevice? Device { get; set; }
public Key Key { get; set; }

8
src/Avalonia.Input/KeyboardDevice.cs

@ -8,9 +8,9 @@ namespace Avalonia.Input
{
public class KeyboardDevice : IKeyboardDevice, INotifyPropertyChanged
{
private IInputElement _focusedElement;
private IInputElement? _focusedElement;
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
public static IKeyboardDevice Instance => AvaloniaLocator.Current.GetService<IKeyboardDevice>();
@ -18,7 +18,7 @@ namespace Avalonia.Input
public IFocusManager FocusManager => AvaloniaLocator.Current.GetService<IFocusManager>();
public IInputElement FocusedElement
public IInputElement? FocusedElement
{
get
{
@ -33,7 +33,7 @@ namespace Avalonia.Input
}
public void SetFocusedElement(
IInputElement element,
IInputElement? element,
NavigationMethod method,
KeyModifiers keyModifiers)
{

13
src/Avalonia.Input/KeyboardNavigationHandler.cs

@ -13,7 +13,7 @@ namespace Avalonia.Input
/// <summary>
/// The window to which the handler belongs.
/// </summary>
private IInputRoot _owner;
private IInputRoot? _owner;
/// <summary>
/// Sets the owner of the keyboard navigation handler.
@ -24,15 +24,12 @@ namespace Avalonia.Input
/// </remarks>
public void SetOwner(IInputRoot owner)
{
Contract.Requires<ArgumentNullException>(owner != null);
if (_owner != null)
{
throw new InvalidOperationException("AccessKeyHandler owner has already been set.");
}
_owner = owner;
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
_owner.AddHandler(InputElement.KeyDownEvent, OnKeyDown);
}
@ -45,11 +42,11 @@ namespace Avalonia.Input
/// The next element in the specified direction, or null if <paramref name="element"/>
/// was the last in the requested direction.
/// </returns>
public static IInputElement GetNext(
public static IInputElement? GetNext(
IInputElement element,
NavigationDirection direction)
{
Contract.Requires<ArgumentNullException>(element != null);
element = element ?? throw new ArgumentNullException(nameof(element));
var customHandler = element.GetSelfAndVisualAncestors()
.OfType<ICustomKeyboardNavigation>()
@ -97,7 +94,7 @@ namespace Avalonia.Input
NavigationDirection direction,
KeyModifiers keyModifiers = KeyModifiers.None)
{
Contract.Requires<ArgumentNullException>(element != null);
element = element ?? throw new ArgumentNullException(nameof(element));
var next = GetNext(element, direction);

73
src/Avalonia.Input/MouseDevice.cs

@ -20,7 +20,7 @@ namespace Avalonia.Input
private readonly Pointer _pointer;
private bool _disposed;
public MouseDevice(Pointer pointer = null)
public MouseDevice(Pointer? pointer = null)
{
_pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
}
@ -34,7 +34,7 @@ namespace Avalonia.Input
/// <see cref="Capture"/> method.
/// </remarks>
[Obsolete("Use IPointer instead")]
public IInputElement Captured => _pointer.Captured;
public IInputElement? Captured => _pointer.Captured;
/// <summary>
/// Gets the mouse position, in screen coordinates.
@ -54,7 +54,7 @@ namespace Avalonia.Input
/// within the control's bounds or not. The current mouse capture control is exposed
/// by the <see cref="Captured"/> property.
/// </remarks>
public void Capture(IInputElement control)
public void Capture(IInputElement? control)
{
_pointer.Capture(control);
}
@ -66,7 +66,7 @@ namespace Avalonia.Input
/// <returns>The mouse position in the control's coordinates.</returns>
public Point GetPosition(IVisual relativeTo)
{
Contract.Requires<ArgumentNullException>(relativeTo != null);
relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo));
if (relativeTo.VisualRoot == null)
{
@ -75,7 +75,7 @@ namespace Avalonia.Input
var rootPoint = relativeTo.VisualRoot.PointToClient(Position);
var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo);
return rootPoint * transform.Value;
return rootPoint * transform!.Value;
}
public void ProcessRawEvent(RawInputEventArgs e)
@ -126,7 +126,7 @@ namespace Avalonia.Input
private void ProcessRawEvent(RawPointerEventArgs e)
{
Contract.Requires<ArgumentNullException>(e != null);
e = e ?? throw new ArgumentNullException(nameof(e));
var mouse = (MouseDevice)e.Device;
if(mouse._disposed)
@ -173,8 +173,8 @@ namespace Avalonia.Input
private void LeaveWindow(IMouseDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
ClearPointerOver(this, timestamp, root, properties, inputModifiers);
}
@ -214,8 +214,8 @@ namespace Avalonia.Input
PointerPointProperties properties,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
var hit = HitTest(root, p);
@ -250,10 +250,10 @@ namespace Avalonia.Input
private bool MouseMove(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
IInputElement source;
IInputElement? source;
if (_pointer.Captured == null)
{
@ -265,18 +265,23 @@ namespace Avalonia.Input
source = _pointer.Captured;
}
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root,
p, timestamp, properties, inputModifiers);
if (source is object)
{
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root,
p, timestamp, properties, inputModifiers);
source?.RaiseEvent(e);
return e.Handled;
source.RaiseEvent(e);
return e.Handled;
}
return false;
}
private bool MouseUp(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
var hit = HitTest(root, p);
@ -298,8 +303,8 @@ namespace Avalonia.Input
PointerPointProperties props,
Vector delta, KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
var hit = HitTest(root, p);
@ -317,21 +322,21 @@ namespace Avalonia.Input
private IInteractive GetSource(IVisual hit)
{
Contract.Requires<ArgumentNullException>(hit != null);
hit = hit ?? throw new ArgumentNullException(nameof(hit));
return _pointer.Captured ??
(hit as IInteractive) ??
hit.GetSelfAndVisualAncestors().OfType<IInteractive>().FirstOrDefault();
}
private IInputElement HitTest(IInputElement root, Point p)
private IInputElement? HitTest(IInputElement root, Point p)
{
Contract.Requires<ArgumentNullException>(root != null);
root = root ?? throw new ArgumentNullException(nameof(root));
return _pointer.Captured ?? root.InputHitTest(p);
}
PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive source,
PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive? source,
PointerPointProperties properties,
KeyModifiers inputModifiers)
{
@ -343,8 +348,8 @@ namespace Avalonia.Input
PointerPointProperties properties,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
var element = root.PointerOverElement;
var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers);
@ -384,12 +389,12 @@ namespace Avalonia.Input
}
}
private IInputElement SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p,
private IInputElement? SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p,
PointerPointProperties properties,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
var element = root.InputHitTest(p);
@ -412,11 +417,11 @@ namespace Avalonia.Input
PointerPointProperties properties,
KeyModifiers inputModifiers)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
Contract.Requires<ArgumentNullException>(element != null);
device = device ?? throw new ArgumentNullException(nameof(device));
root = root ?? throw new ArgumentNullException(nameof(root));
element = element ?? throw new ArgumentNullException(nameof(element));
IInputElement branch = null;
IInputElement? branch = null;
var el = element;

42
src/Avalonia.Input/Navigation/TabNavigation.cs

@ -22,15 +22,17 @@ namespace Avalonia.Input.Navigation
/// The next element in the specified direction, or null if <paramref name="element"/>
/// was the last in the requested direction.
/// </returns>
public static IInputElement GetNextInTabOrder(
public static IInputElement? GetNextInTabOrder(
IInputElement element,
NavigationDirection direction,
bool outsideElement = false)
{
Contract.Requires<ArgumentNullException>(element != null);
Contract.Requires<ArgumentException>(
direction == NavigationDirection.Next ||
direction == NavigationDirection.Previous);
element = element ?? throw new ArgumentNullException(nameof(element));
if (direction != NavigationDirection.Next && direction != NavigationDirection.Previous)
{
throw new ArgumentException("Invalid direction: must be Next or Previous.");
}
var container = element.GetVisualParent<IInputElement>();
@ -110,7 +112,7 @@ namespace Avalonia.Input.Navigation
if (customNext.handled)
{
yield return customNext.next;
yield return customNext.next!;
}
else
{
@ -143,12 +145,14 @@ namespace Avalonia.Input.Navigation
/// If true will not descend into <paramref name="element"/> to find next control.
/// </param>
/// <returns>The next element, or null if the element is the last.</returns>
private static IInputElement GetNextInContainer(
private static IInputElement? GetNextInContainer(
IInputElement element,
IInputElement container,
NavigationDirection direction,
bool outsideElement)
{
IInputElement? e = element;
if (direction == NavigationDirection.Next && !outsideElement)
{
var descendant = GetFocusableDescendants(element, direction).FirstOrDefault();
@ -167,13 +171,13 @@ namespace Avalonia.Input.Navigation
// INavigableContainer.
if (navigable != null)
{
while (element != null)
while (e != null)
{
element = navigable.GetControl(direction, element, false);
e = navigable.GetControl(direction, e, false);
if (element != null &&
element.CanFocus() &&
KeyboardNavigation.GetIsTabStop((InputElement) element))
if (e != null &&
e.CanFocus() &&
KeyboardNavigation.GetIsTabStop((InputElement)e))
{
break;
}
@ -183,12 +187,12 @@ namespace Avalonia.Input.Navigation
{
// TODO: Do a spatial search here if the container doesn't implement
// INavigableContainer.
element = null;
e = null;
}
if (element != null && direction == NavigationDirection.Previous)
if (e != null && direction == NavigationDirection.Previous)
{
var descendant = GetFocusableDescendants(element, direction).LastOrDefault();
var descendant = GetFocusableDescendants(e, direction).LastOrDefault();
if (descendant != null)
{
@ -196,7 +200,7 @@ namespace Avalonia.Input.Navigation
}
}
return element;
return e;
}
return null;
@ -209,13 +213,13 @@ namespace Avalonia.Input.Navigation
/// <param name="container">The container.</param>
/// <param name="direction">The direction of the search.</param>
/// <returns>The first element, or null if there are no more elements.</returns>
private static IInputElement GetFirstInNextContainer(
private static IInputElement? GetFirstInNextContainer(
IInputElement element,
IInputElement container,
NavigationDirection direction)
{
var parent = container.GetVisualParent<IInputElement>();
IInputElement next = null;
IInputElement? next = null;
if (parent != null)
{
@ -268,7 +272,7 @@ namespace Avalonia.Input.Navigation
return next;
}
private static (bool handled, IInputElement next) GetCustomNext(IInputElement element,
private static (bool handled, IInputElement? next) GetCustomNext(IInputElement element,
NavigationDirection direction)
{
if (element is ICustomKeyboardNavigation custom)

9
src/Avalonia.Input/Pointer.cs

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
namespace Avalonia.Input
@ -20,7 +19,7 @@ namespace Avalonia.Input
public int Id { get; }
IInputElement FindCommonParent(IInputElement control1, IInputElement control2)
IInputElement? FindCommonParent(IInputElement? control1, IInputElement? control2)
{
if (control1 == null || control2 == null)
return null;
@ -28,12 +27,12 @@ namespace Avalonia.Input
return control2.GetSelfAndVisualAncestors().OfType<IInputElement>().FirstOrDefault(seen.Contains);
}
protected virtual void PlatformCapture(IInputElement element)
protected virtual void PlatformCapture(IInputElement? element)
{
}
public void Capture(IInputElement control)
public void Capture(IInputElement? control)
{
if (Captured != null)
Captured.DetachedFromVisualTree -= OnCaptureDetached;
@ -66,7 +65,7 @@ namespace Avalonia.Input
}
public IInputElement Captured { get; private set; }
public IInputElement? Captured { get; private set; }
public PointerType Type { get; }
public bool IsPrimary { get; }

14
src/Avalonia.Input/PointerEventArgs.cs

@ -7,14 +7,14 @@ namespace Avalonia.Input
{
public class PointerEventArgs : RoutedEventArgs
{
private readonly IVisual _rootVisual;
private readonly IVisual? _rootVisual;
private readonly Point _rootVisualPosition;
private readonly PointerPointProperties _properties;
public PointerEventArgs(RoutedEvent routedEvent,
IInteractive source,
IInteractive? source,
IPointer pointer,
IVisual rootVisual, Point rootVisualPosition,
IVisual? rootVisual, Point rootVisualPosition,
ulong timestamp,
PointerPointProperties properties,
KeyModifiers modifiers)
@ -40,8 +40,8 @@ namespace Avalonia.Input
public void ProcessRawEvent(RawInputEventArgs ev) => throw new NotSupportedException();
public IInputElement Captured => _ev.Pointer.Captured;
public void Capture(IInputElement control)
public IInputElement? Captured => _ev.Pointer.Captured;
public void Capture(IInputElement? control)
{
_ev.Pointer.Capture(control);
}
@ -52,7 +52,7 @@ namespace Avalonia.Input
public IPointer Pointer { get; }
public ulong Timestamp { get; }
private IPointerDevice _device;
private IPointerDevice? _device;
[Obsolete("Use Pointer to get pointer-specific information")]
public IPointerDevice Device => _device ?? (_device = new EmulatedDevice(this));
@ -76,7 +76,7 @@ namespace Avalonia.Input
public KeyModifiers KeyModifiers { get; }
public Point GetPosition(IVisual relativeTo)
public Point GetPosition(IVisual? relativeTo)
{
if (_rootVisual == null)
return default;

2
src/Avalonia.Input/Raw/RawDragEventType.cs

@ -7,4 +7,4 @@
DragLeave,
Drop
}
}
}

2
src/Avalonia.Input/Raw/RawInputEventArgs.cs

@ -21,7 +21,7 @@ namespace Avalonia.Input.Raw
/// <param name="root">The root from which the event originates.</param>
public RawInputEventArgs(IInputDevice device, ulong timestamp, IInputRoot root)
{
Contract.Requires<ArgumentNullException>(device != null);
device = device ?? throw new ArgumentNullException(nameof(device));
Device = device;
Timestamp = timestamp;

4
src/Avalonia.Input/TextInputEventArgs.cs

@ -4,8 +4,8 @@ namespace Avalonia.Input
{
public class TextInputEventArgs : RoutedEventArgs
{
public IKeyboardDevice Device { get; set; }
public IKeyboardDevice? Device { get; set; }
public string Text { get; set; }
public string? Text { get; set; }
}
}

Loading…
Cancel
Save