Browse Source

Nullable annotations for LinuxFramebuffer (#17489)

pull/17499/head
Julien Lebosquain 1 year ago
committed by GitHub
parent
commit
601425d519
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  2. 7
      src/Linux/Avalonia.LinuxFramebuffer/EpollDispatcherImpl.cs
  3. 27
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  4. 8
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevBackend.cs
  5. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDevice.cs
  6. 2
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDeviceDescription.cs
  7. 14
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevTouchScreen.cs
  8. 22
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs
  9. 2
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Touch.cs
  10. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
  11. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
  12. 4
      src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs
  13. 4
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs
  14. 19
      src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
  15. 4
      src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevBackBuffer.cs
  16. 2
      src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevOutputOptions.cs
  17. 8
      src/Linux/Avalonia.LinuxFramebuffer/Output/FbdevOutput.cs
  18. 1
      src/Linux/Avalonia.LinuxFramebuffer/Output/IGlOutputBackend.cs

1
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@ -10,4 +10,5 @@
<Compile Include="..\..\Shared\RawEventGrouping.cs" />
</ItemGroup>
<Import Project="..\..\..\build\TrimmingEnable.props" />
<Import Project="..\..\..\build\NullableEnable.props" />
</Project>

7
src/Linux/Avalonia.LinuxFramebuffer/EpollDispatcherImpl.cs

@ -11,7 +11,7 @@ namespace Avalonia.LinuxFramebuffer;
internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl
{
private readonly ManagedDispatcherImpl.IManagedDispatcherInputProvider _inputProvider;
private Thread _mainThread;
private readonly Thread _mainThread;
[StructLayout(LayoutKind.Explicit)]
private struct epoll_data
@ -161,6 +161,7 @@ internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl
itimerspec timer = new()
{
it_interval = default,
it_value = new()
{
tv_sec = new IntPtr(Math.Min((int)waitFor.TotalSeconds, 100)),
@ -219,8 +220,8 @@ internal unsafe class EpollDispatcherImpl : IControlledDispatcherImpl
public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _mainThread;
public event Action Signaled;
public event Action Timer;
public event Action? Signaled;
public event Action? Timer;
public void UpdateTimer(long? dueTimeInMs)
{

27
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@ -6,7 +6,6 @@ using Avalonia.Input.Raw;
using Avalonia.LinuxFramebuffer.Input;
using Avalonia.LinuxFramebuffer.Output;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
@ -18,7 +17,7 @@ using Avalonia.Rendering.Composition;
private readonly IInputBackend _inputBackend;
private readonly RawEventGrouper _inputQueue;
public IInputRoot InputRoot { get; private set; }
public IInputRoot? InputRoot { get; private set; }
public FramebufferToplevelImpl(IOutputBackend outputBackend, IInputBackend inputBackend)
{
@ -49,28 +48,28 @@ using Avalonia.Rendering.Composition;
public PixelPoint PointToScreen(Point p) => PixelPoint.FromPoint(p, 1);
public void SetCursor(ICursorImpl cursor)
public void SetCursor(ICursorImpl? cursor)
{
}
public double DesktopScaling => 1;
public IPlatformHandle Handle { get; }
public IPlatformHandle? Handle => null;
public Size ClientSize => ScaledSize;
public Size? FrameSize => null;
public IMouseDevice MouseDevice => new MouseDevice();
public IPopupImpl CreatePopup() => null;
public IMouseDevice MouseDevice { get; } = new MouseDevice();
public IPopupImpl? CreatePopup() => null;
public double RenderScaling => _outputBackend.Scaling;
public IEnumerable<object> Surfaces { get; }
public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect> Paint { get; set; }
public Action<Size, WindowResizeReason> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public Action<RawInputEventArgs>? Input { get; set; }
public Action<Rect>? Paint { get; set; }
public Action<Size, WindowResizeReason>? Resized { get; set; }
public Action<double>? ScalingChanged { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
public Action Closed { get; set; }
public Action LostFocus { get; set; }
public Action? Closed { get; set; }
public Action? LostFocus { get; set; }
public Size ScaledSize => _outputBackend.PixelSize.ToSize(RenderScaling);
@ -81,6 +80,6 @@ using Avalonia.Rendering.Composition;
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { }
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
public object TryGetFeature(Type featureType) => null;
public object? TryGetFeature(Type featureType) => null;
}
}

8
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevBackend.cs

@ -12,8 +12,8 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
private readonly EvDevDeviceDescription[] _deviceDescriptions;
private readonly List<EvDevDeviceHandler> _handlers = new List<EvDevDeviceHandler>();
private int _epoll;
private Action<RawInputEventArgs> _onInput;
private IInputRoot _inputRoot;
private Action<RawInputEventArgs>? _onInput;
private IInputRoot? _inputRoot;
public EvDevBackend(EvDevDeviceDescription[] devices)
{
@ -53,7 +53,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
for (var c = 0; c < _deviceDescriptions.Length; c++)
{
var description = _deviceDescriptions[c];
var dev = EvDevDevice.Open(description.Path);
var dev = EvDevDevice.Open(description.Path ?? string.Empty);
EvDevDeviceHandler handler;
if (description is EvDevTouchScreenDeviceDescription touch)
handler = new EvDevSingleTouchScreen(dev, touch, info) { InputRoot = _inputRoot };
@ -86,7 +86,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
{
if (key.StartsWith("AVALONIA_EVDEV_DEVICE_"))
{
var value = (string)env[key];
var value = (string)env[key]!;
deviceDescriptions.Add(EvDevDeviceDescription.ParseFromEnv(value));
}
}

4
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDevice.cs

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace Avalonia.LinuxFramebuffer.Input.EvDev
@ -10,7 +8,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
{
public int Fd { get; }
private IntPtr _dev;
public string Name { get; }
public string? Name { get; }
public List<EvType> EventTypes { get; private set; } = new List<EvType>();
public input_absinfo? AbsX { get; }
public input_absinfo? AbsY { get; }

2
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDeviceDescription.cs

@ -10,7 +10,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
}
public string Path { get; set; }
public string? Path { get; set; }
internal static EvDevDeviceDescription ParseFromEnv(string env)
{

14
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevTouchScreen.cs

@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Input;
using Avalonia.Input.Raw;
@ -90,14 +91,23 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
internal abstract class EvDevDeviceHandler
{
public event Action<RawInputEventArgs> OnEvent;
private IInputRoot? _inputRoot;
public event Action<RawInputEventArgs>? OnEvent;
public EvDevDeviceHandler(EvDevDevice device)
{
Device = device;
}
public EvDevDevice Device { get; }
public IInputRoot InputRoot { get; set; }
[AllowNull]
public IInputRoot InputRoot
{
get => _inputRoot ?? throw new InvalidOperationException($"{nameof(InputRoot)} hasn't been set");
set => _inputRoot = value;
}
public void HandleEvents()
{

22
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs

@ -16,14 +16,14 @@ public partial class LibInputBackend
{
var modifiers = RawInputModifiers.None; //TODO: support input modifiers
var pev = libinput_event_get_pointer_event(ev);
var info = _screen.ScaledSize;
var info = _screen!.ScaledSize;
var ts = libinput_event_pointer_get_time_usec(pev) / 1000;
switch (type)
{
case LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
_mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width),
libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
ScheduleInput(new RawPointerEventArgs(_mouse, ts, InputRoot, RawPointerEventType.Move, _mousePosition,
modifiers));
break;
case LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON:
@ -31,20 +31,20 @@ public partial class LibInputBackend
var button = (EvKey)libinput_event_pointer_get_button(pev);
var buttonState = libinput_event_pointer_get_button_state(pev);
RawPointerEventArgs evnt = button switch
RawPointerEventArgs? evnt = button switch
{
EvKey.BTN_LEFT when buttonState == 1
=> new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonDown, _mousePosition, modifiers),
=> new(_mouse, ts, InputRoot, RawPointerEventType.LeftButtonDown, _mousePosition, modifiers),
EvKey.BTN_LEFT when buttonState == 0
=> new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonUp, _mousePosition, modifiers),
=> new(_mouse, ts, InputRoot, RawPointerEventType.LeftButtonUp, _mousePosition, modifiers),
EvKey.BTN_RIGHT when buttonState == 1
=> new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonUp, _mousePosition, modifiers),
=> new(_mouse, ts, InputRoot, RawPointerEventType.RightButtonUp, _mousePosition, modifiers),
EvKey.BTN_RIGHT when buttonState == 2
=> new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonDown, _mousePosition, modifiers),
=> new(_mouse, ts, InputRoot, RawPointerEventType.RightButtonDown, _mousePosition, modifiers),
EvKey.BTN_MIDDLE when buttonState == 1
=> new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonDown, _mousePosition, modifiers),
=> new(_mouse, ts, InputRoot, RawPointerEventType.MiddleButtonDown, _mousePosition, modifiers),
EvKey.BTN_MIDDLE when buttonState == 2
=> new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonUp, _mousePosition, modifiers),
=> new(_mouse, ts, InputRoot, RawPointerEventType.MiddleButtonUp, _mousePosition, modifiers),
_ => default,
};
if (evnt is not null)
@ -70,7 +70,7 @@ public partial class LibInputBackend
LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
ScheduleInput(new RawMouseWheelEventArgs(_mouse
, ts
, _inputRoot
, InputRoot
, _mousePosition
, new Vector(0, -value)
, modifiers));
@ -94,7 +94,7 @@ public partial class LibInputBackend
LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) / 120);
ScheduleInput(new RawMouseWheelEventArgs(_mouse
, ts
, _inputRoot
, InputRoot
, _mousePosition
, value
, modifiers));

2
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Touch.cs

@ -18,7 +18,7 @@ public partial class LibInputBackend
return;
if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME)
{
var info = _screen.ScaledSize;
var info = _screen!.ScaledSize;
var slot = libinput_event_touch_get_slot(tev);
Point pt;

4
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs

@ -1,4 +1,3 @@
#nullable enable
using System;
using System.IO;
using System.Threading;
@ -25,6 +24,9 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
_options = options;
}
private IInputRoot InputRoot
=> _inputRoot ?? throw new InvalidOperationException($"{nameof(InputRoot)} hasn't been set");
private unsafe void InputThread(IntPtr ctx, LibInputBackendOptions options)
{
var fd = libinput_get_fd(ctx);

4
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs

@ -13,7 +13,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
static int OpenRestricted(IntPtr path, int flags, IntPtr userData)
{
var fd = NativeUnsafeMethods.open(Marshal.PtrToStringAnsi(path), flags, 0);
var fd = NativeUnsafeMethods.open(Marshal.PtrToStringAnsi(path) ?? string.Empty, flags, 0);
if (fd == -1)
return -Marshal.GetLastWin32Error();
@ -31,7 +31,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
{
s_Interface = (IntPtr*)Marshal.AllocHGlobal(IntPtr.Size * 2);
IntPtr Convert<TDelegate>(TDelegate del)
IntPtr Convert<TDelegate>(TDelegate del) where TDelegate : notnull
{
GCHandle.Alloc(del);
return Marshal.GetFunctionPointerForDelegate(del);

4
src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
@ -8,7 +7,6 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Embedding;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.LinuxFramebuffer;
@ -21,8 +19,6 @@ using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
#nullable enable
namespace Avalonia.LinuxFramebuffer
{
internal class LinuxFramebufferIconLoaderStub : IPlatformIconLoader

4
src/Linux/Avalonia.LinuxFramebuffer/Output/DrmBindings.cs

@ -63,7 +63,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public PixelSize Resolution => new PixelSize(Mode.hdisplay, Mode.vdisplay);
public bool IsPreferred => Mode.type.HasAllFlags(DrmModeType.DRM_MODE_TYPE_PREFERRED);
public string Name { get; }
public string? Name { get; }
}
unsafe class DrmEncoder
@ -141,7 +141,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public unsafe class DrmCard : IDisposable
{
public int Fd { get; private set; }
public DrmCard(string path = null)
public DrmCard(string? path = null)
{
if (path == null)
{

19
src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.OpenGL;
@ -41,19 +42,19 @@ namespace Avalonia.LinuxFramebuffer.Output
public IPlatformGraphics PlatformGraphics { get; private set; }
public DrmOutput(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo,
DrmOutputOptions options = null)
DrmOutputOptions? options = null)
{
if (options != null)
_outputOptions = options;
Init(card, resources, connector, modeInfo);
}
public DrmOutput(string path = null, bool connectorsForceProbe = false, DrmOutputOptions options = null)
public DrmOutput(string? path = null, bool connectorsForceProbe = false, DrmOutputOptions? options = null)
:this(new DrmCard(path), connectorsForceProbe, options)
{
}
public DrmOutput(DrmCard card, bool connectorsForceProbe = false, DrmOutputOptions options = null)
public DrmOutput(DrmCard card, bool connectorsForceProbe = false, DrmOutputOptions? options = null)
{
if (options != null)
_outputOptions = options;
@ -78,7 +79,7 @@ namespace Avalonia.LinuxFramebuffer.Output
if (connector == null)
throw new InvalidOperationException("Unable to find connected DRM connector");
DrmModeInfo mode = null;
DrmModeInfo? mode = null;
if (options?.VideoMode != null)
{
@ -157,6 +158,12 @@ namespace Avalonia.LinuxFramebuffer.Output
}
[MemberNotNull(nameof(_card))]
[MemberNotNull(nameof(PlatformGraphics))]
[MemberNotNull(nameof(FbDestroyDelegate))]
[MemberNotNull(nameof(_eglDisplay))]
[MemberNotNull(nameof(_eglSurface))]
[MemberNotNull(nameof(_deferredContext))]
void Init(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo)
{
FbDestroyDelegate = FbDestroyCallback;
@ -232,7 +239,7 @@ namespace Avalonia.LinuxFramebuffer.Output
if (_outputOptions.EnableInitialBufferSwapping)
{
//Go trough two cycles of buffer swapping (there are render artifacts otherwise)
//Go through two cycles of buffer swapping (there are render artifacts otherwise)
for (var c = 0; c < 2; c++)
using (CreateGlRenderTarget().BeginDraw())
{
@ -330,7 +337,7 @@ namespace Avalonia.LinuxFramebuffer.Output
public double Scaling => _parent.Scaling;
public bool IsYFlipped { get; }
public bool IsYFlipped => false;
}
public IGlPlatformSurfaceRenderingSession BeginDraw()

4
src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevBackBuffer.cs

@ -1,6 +1,4 @@
#nullable enable
using System;
using System;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Logging;

2
src/Linux/Avalonia.LinuxFramebuffer/Output/FbDevOutputOptions.cs

@ -1,5 +1,3 @@
#nullable enable
using Avalonia.Platform;
namespace Avalonia.LinuxFramebuffer.Output;

8
src/Linux/Avalonia.LinuxFramebuffer/Output/FbdevOutput.cs

@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
using Avalonia.Controls.Platform.Surfaces;
@ -14,7 +15,7 @@ namespace Avalonia.LinuxFramebuffer
private fb_var_screeninfo _varInfo;
private IntPtr _mappedLength;
private IntPtr _mappedAddress;
private FbDevBackBuffer _backBuffer;
private FbDevBackBuffer? _backBuffer;
private readonly FbDevOutputOptions _options;
private bool _lockedAtLeastOnce;
public double Scaling { get; set; }
@ -24,7 +25,7 @@ namespace Avalonia.LinuxFramebuffer
/// </summary>
/// <param name="fileName">The frame buffer device name.
/// Defaults to the value in environment variable FRAMEBUFFER or /dev/fb0 when FRAMEBUFFER is not set</param>
public FbdevOutput(string fileName = null) : this(fileName, null)
public FbdevOutput(string? fileName = null) : this(fileName, null)
{
}
@ -36,7 +37,7 @@ namespace Avalonia.LinuxFramebuffer
/// <param name="format">The required pixel format for the frame buffer.
/// A null value will leave the frame buffer in the current pixel format.
/// Otherwise sets the frame buffer to the required format</param>
public FbdevOutput(string fileName, PixelFormat? format) : this(new FbDevOutputOptions()
public FbdevOutput(string? fileName, PixelFormat? format) : this(new FbDevOutputOptions()
{
FileName = fileName,
PixelFormat = format
@ -68,6 +69,7 @@ namespace Avalonia.LinuxFramebuffer
}
}
[MemberNotNull(nameof(Id))]
void Init(PixelFormat? format)
{
fixed (void* pnfo = &_varInfo)

1
src/Linux/Avalonia.LinuxFramebuffer/Output/IGlOutputBackend.cs

@ -1,4 +1,3 @@
using Avalonia.OpenGL;
using Avalonia.Platform;
namespace Avalonia.LinuxFramebuffer.Output

Loading…
Cancel
Save