diff --git a/Avalonia.sln b/Avalonia.sln
index 25c7daf080..8d2479a663 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -38,6 +38,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
EndProjectSection
diff --git a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
index a5cb207223..3b1c6cc7b1 100644
--- a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
+++ b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
@@ -5,6 +5,10 @@
enable
+
+
+
+
diff --git a/src/Avalonia.FreeDesktop/DBusCallQueue.cs b/src/Avalonia.FreeDesktop/DBusCallQueue.cs
index 5cd748be02..e7c07dcbf9 100644
--- a/src/Avalonia.FreeDesktop/DBusCallQueue.cs
+++ b/src/Avalonia.FreeDesktop/DBusCallQueue.cs
@@ -8,10 +8,9 @@ namespace Avalonia.FreeDesktop
{
private readonly Func _errorHandler;
- class Item
+ record Item(Func Callback)
{
- public Func Callback;
- public Action OnFinish;
+ public Action? OnFinish;
}
private Queue- _q = new Queue
- ();
private bool _processing;
@@ -23,19 +22,15 @@ namespace Avalonia.FreeDesktop
public void Enqueue(Func cb)
{
- _q.Enqueue(new Item
- {
- Callback = cb
- });
+ _q.Enqueue(new Item(cb));
Process();
}
public Task EnqueueAsync(Func cb)
{
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
- _q.Enqueue(new Item
+ _q.Enqueue(new Item(cb)
{
- Callback = cb,
OnFinish = e =>
{
if (e == null)
@@ -51,13 +46,12 @@ namespace Avalonia.FreeDesktop
public Task EnqueueAsync(Func> cb)
{
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
- _q.Enqueue(new Item
- {
- Callback = async () =>
+ _q.Enqueue(new Item(async () =>
{
var res = await cb();
tcs.TrySetResult(res);
- },
+ })
+ {
OnFinish = e =>
{
if (e != null)
diff --git a/src/Avalonia.FreeDesktop/DBusHelper.cs b/src/Avalonia.FreeDesktop/DBusHelper.cs
index 7204e51dbd..9f9d75b411 100644
--- a/src/Avalonia.FreeDesktop/DBusHelper.cs
+++ b/src/Avalonia.FreeDesktop/DBusHelper.cs
@@ -17,7 +17,7 @@ namespace Avalonia.FreeDesktop
private readonly object _lock = new();
private SynchronizationContext? _ctx;
- public override void Post(SendOrPostCallback d, object state)
+ public override void Post(SendOrPostCallback d, object? state)
{
lock (_lock)
{
@@ -29,7 +29,7 @@ namespace Avalonia.FreeDesktop
}
}
- public override void Send(SendOrPostCallback d, object state)
+ public override void Send(SendOrPostCallback d, object? state)
{
lock (_lock)
{
diff --git a/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs b/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs
index 864c579319..eef865d458 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs
@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
-using Avalonia.FreeDesktop.DBusIme.Fcitx;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Logging;
@@ -26,7 +24,7 @@ namespace Avalonia.FreeDesktop.DBusIme
return (im, im);
}
}
-
+
internal abstract class DBusTextInputMethodBase : IX11InputMethodControl, ITextInputMethodImpl
{
private List _disposables = new List();
@@ -34,7 +32,7 @@ namespace Avalonia.FreeDesktop.DBusIme
protected Connection Connection { get; }
private readonly string[] _knownNames;
private bool _connecting;
- private string _currentName;
+ private string? _currentName;
private DBusCallQueue _queue;
private bool _controlActive, _windowActive;
private bool? _imeActive;
@@ -42,9 +40,9 @@ namespace Avalonia.FreeDesktop.DBusIme
private PixelRect? _lastReportedRect;
private double _scaling = 1;
private PixelPoint _windowPosition;
-
+
protected bool IsConnected => _currentName != null;
-
+
public DBusTextInputMethodBase(Connection connection, params string[] knownNames)
{
_queue = new DBusCallQueue(QueueOnError);
@@ -58,18 +56,18 @@ namespace Avalonia.FreeDesktop.DBusIme
foreach (var name in _knownNames)
_disposables.Add(await Connection.ResolveServiceOwnerAsync(name, OnNameChange));
}
-
+
protected abstract Task Connect(string name);
protected string GetAppName() =>
- Application.Current.Name ?? Assembly.GetEntryAssembly()?.GetName()?.Name ?? "Avalonia";
-
+ Application.Current?.Name ?? Assembly.GetEntryAssembly()?.GetName()?.Name ?? "Avalonia";
+
private async void OnNameChange(ServiceOwnerChangedEventArgs args)
{
if (args.NewOwner != null && _currentName == null)
{
_onlineNamesQueue.Enqueue(args.ServiceName);
- if(!_connecting)
+ if (!_connecting)
{
_connecting = true;
try
@@ -98,25 +96,25 @@ namespace Avalonia.FreeDesktop.DBusIme
_connecting = false;
}
}
-
+
}
-
+
// IME has crashed
if (args.NewOwner == null && args.ServiceName == _currentName)
{
_currentName = null;
- foreach(var s in _disposables)
+ foreach (var s in _disposables)
s.Dispose();
_disposables.Clear();
-
+
OnDisconnected();
Reset();
-
+
// Watch again
Watch();
}
}
-
+
protected virtual Task Disconnect()
{
return Task.CompletedTask;
@@ -124,7 +122,7 @@ namespace Avalonia.FreeDesktop.DBusIme
protected virtual void OnDisconnected()
{
-
+
}
protected virtual void Reset()
@@ -149,10 +147,14 @@ namespace Avalonia.FreeDesktop.DBusIme
OnDisconnected();
_currentName = null;
}
-
+
protected void Enqueue(Func cb) => _queue.Enqueue(cb);
- protected void AddDisposable(IDisposable d) => _disposables.Add(d);
+ protected void AddDisposable(IDisposable? d)
+ {
+ if(d is { })
+ _disposables.Add(d);
+ }
public void Dispose()
{
@@ -198,7 +200,7 @@ namespace Avalonia.FreeDesktop.DBusIme
UpdateActive();
}
- void ITextInputMethodImpl.SetClient(ITextInputMethodClient client)
+ void ITextInputMethodImpl.SetClient(ITextInputMethodClient? client)
{
_controlActive = client is { };
UpdateActive();
@@ -225,7 +227,7 @@ namespace Avalonia.FreeDesktop.DBusIme
}
}
- private Action _onCommit;
+ private Action? _onCommit;
event Action IX11InputMethodControl.Commit
{
add => _onCommit += value;
@@ -234,7 +236,7 @@ namespace Avalonia.FreeDesktop.DBusIme
protected void FireCommit(string s) => _onCommit?.Invoke(s);
- private Action _onForward;
+ private Action? _onForward;
event Action IX11InputMethodControl.ForwardKey
{
add => _onForward += value;
diff --git a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxDBus.cs b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxDBus.cs
index 7ce2339763..06afacaa29 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxDBus.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxDBus.cs
@@ -31,15 +31,15 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
Task SetSurroundingTextPositionAsync(uint Cursor, uint Anchor);
Task DestroyICAsync();
Task ProcessKeyEventAsync(uint Keyval, uint Keycode, uint State, int Type, uint Time);
- Task WatchEnableIMAsync(Action handler, Action onError = null);
- Task WatchCloseIMAsync(Action handler, Action onError = null);
- Task WatchCommitStringAsync(Action handler, Action onError = null);
- Task WatchCurrentIMAsync(Action<(string name, string uniqueName, string langCode)> handler, Action onError = null);
- Task WatchUpdatePreeditAsync(Action<(string str, int cursorpos)> handler, Action onError = null);
- Task WatchUpdateFormattedPreeditAsync(Action<((string, int)[] str, int cursorpos)> handler, Action onError = null);
- Task WatchUpdateClientSideUIAsync(Action<(string auxup, string auxdown, string preedit, string candidateword, string imname, int cursorpos)> handler, Action onError = null);
- Task WatchForwardKeyAsync(Action<(uint keyval, uint state, int type)> handler, Action onError = null);
- Task WatchDeleteSurroundingTextAsync(Action<(int offset, uint nchar)> handler, Action onError = null);
+ Task WatchEnableIMAsync(Action handler, Action? onError = null);
+ Task WatchCloseIMAsync(Action handler, Action? onError = null);
+ Task WatchCommitStringAsync(Action handler, Action? onError = null);
+ Task WatchCurrentIMAsync(Action<(string name, string uniqueName, string langCode)> handler, Action? onError = null);
+ Task WatchUpdatePreeditAsync(Action<(string str, int cursorpos)> handler, Action? onError = null);
+ Task WatchUpdateFormattedPreeditAsync(Action<((string, int)[] str, int cursorpos)> handler, Action? onError = null);
+ Task WatchUpdateClientSideUIAsync(Action<(string auxup, string auxdown, string preedit, string candidateword, string imname, int cursorpos)> handler, Action? onError = null);
+ Task WatchForwardKeyAsync(Action<(uint keyval, uint state, int type)> handler, Action? onError = null);
+ Task WatchDeleteSurroundingTextAsync(Action<(int offset, uint nchar)> handler, Action? onError = null);
}
[DBusInterface("org.fcitx.Fcitx.InputContext1")]
@@ -54,11 +54,11 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
Task SetSurroundingTextPositionAsync(uint Cursor, uint Anchor);
Task DestroyICAsync();
Task ProcessKeyEventAsync(uint Keyval, uint Keycode, uint State, bool Type, uint Time);
- Task WatchCommitStringAsync(Action handler, Action onError = null);
- Task WatchCurrentIMAsync(Action<(string name, string uniqueName, string langCode)> handler, Action onError = null);
- Task WatchUpdateFormattedPreeditAsync(Action<((string, int)[] str, int cursorpos)> handler, Action onError = null);
- Task WatchForwardKeyAsync(Action<(uint keyval, uint state, bool type)> handler, Action onError = null);
- Task WatchDeleteSurroundingTextAsync(Action<(int offset, uint nchar)> handler, Action onError = null);
+ Task WatchCommitStringAsync(Action handler, Action? onError = null);
+ Task WatchCurrentIMAsync(Action<(string name, string uniqueName, string langCode)> handler, Action? onError = null);
+ Task WatchUpdateFormattedPreeditAsync(Action<((string, int)[] str, int cursorpos)> handler, Action? onError = null);
+ Task WatchForwardKeyAsync(Action<(uint keyval, uint state, bool type)> handler, Action? onError = null);
+ Task WatchDeleteSurroundingTextAsync(Action<(int offset, uint nchar)> handler, Action? onError = null);
}
[DBusInterface("org.fcitx.Fcitx.InputMethod1")]
diff --git a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
index a03ea213aa..6c503edb41 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
@@ -5,8 +5,8 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
{
internal class FcitxICWrapper
{
- private readonly IFcitxInputContext1 _modern;
- private readonly IFcitxInputContext _old;
+ private readonly IFcitxInputContext1? _modern;
+ private readonly IFcitxInputContext? _old;
public FcitxICWrapper(IFcitxInputContext old)
{
@@ -18,34 +18,37 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
_modern = modern;
}
- public Task FocusInAsync() => _old?.FocusInAsync() ?? _modern.FocusInAsync();
+ public Task FocusInAsync() => _old?.FocusInAsync() ?? _modern?.FocusInAsync() ?? Task.CompletedTask;
- public Task FocusOutAsync() => _old?.FocusOutAsync() ?? _modern.FocusOutAsync();
+ public Task FocusOutAsync() => _old?.FocusOutAsync() ?? _modern?.FocusOutAsync() ?? Task.CompletedTask;
- public Task ResetAsync() => _old?.ResetAsync() ?? _modern.ResetAsync();
+ public Task ResetAsync() => _old?.ResetAsync() ?? _modern?.ResetAsync() ?? Task.CompletedTask;
public Task SetCursorRectAsync(int x, int y, int w, int h) =>
- _old?.SetCursorRectAsync(x, y, w, h) ?? _modern.SetCursorRectAsync(x, y, w, h);
- public Task DestroyICAsync() => _old?.DestroyICAsync() ?? _modern.DestroyICAsync();
+ _old?.SetCursorRectAsync(x, y, w, h) ?? _modern?.SetCursorRectAsync(x, y, w, h) ?? Task.CompletedTask;
+ public Task DestroyICAsync() => _old?.DestroyICAsync() ?? _modern?.DestroyICAsync() ?? Task.CompletedTask;
public async Task ProcessKeyEventAsync(uint keyVal, uint keyCode, uint state, int type, uint time)
{
if(_old!=null)
return await _old.ProcessKeyEventAsync(keyVal, keyCode, state, type, time) != 0;
- return await _modern.ProcessKeyEventAsync(keyVal, keyCode, state, type > 0, time);
+ return await (_modern?.ProcessKeyEventAsync(keyVal, keyCode, state, type > 0, time) ?? Task.FromResult(false));
}
- public Task WatchCommitStringAsync(Action handler) =>
- _old?.WatchCommitStringAsync(handler) ?? _modern.WatchCommitStringAsync(handler);
+ public Task WatchCommitStringAsync(Action handler) =>
+ _old?.WatchCommitStringAsync(handler)
+ ?? _modern?.WatchCommitStringAsync(handler)
+ ?? Task.FromResult(default(IDisposable?));
- public Task WatchForwardKeyAsync(Action<(uint keyval, uint state, int type)> handler)
+ public Task WatchForwardKeyAsync(Action<(uint keyval, uint state, int type)> handler)
{
return _old?.WatchForwardKeyAsync(handler)
- ?? _modern.WatchForwardKeyAsync(ev =>
- handler((ev.keyval, ev.state, ev.type ? 1 : 0)));
+ ?? _modern?.WatchForwardKeyAsync(ev =>
+ handler((ev.keyval, ev.state, ev.type ? 1 : 0)))
+ ?? Task.FromResult(default(IDisposable?));
}
public Task SetCapacityAsync(uint flags) =>
- _old?.SetCapacityAsync(flags) ?? _modern.SetCapabilityAsync(flags);
+ _old?.SetCapacityAsync(flags) ?? _modern?.SetCapabilityAsync(flags) ?? Task.CompletedTask;
}
}
diff --git a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
index 0b85965de7..791431dfa7 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
@@ -12,7 +12,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
{
internal class FcitxX11TextInputMethod : DBusTextInputMethodBase
{
- private FcitxICWrapper _context;
+ private FcitxICWrapper? _context;
private FcitxCapabilityFlags? _lastReportedFlags;
public FcitxX11TextInputMethod(Connection connection) : base(connection,
@@ -49,7 +49,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
return true;
}
- protected override Task Disconnect() => _context.DestroyICAsync();
+ protected override Task Disconnect() => _context?.DestroyICAsync() ?? Task.CompletedTask;
protected override void OnDisconnected() => _context = null;
@@ -60,18 +60,18 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
}
protected override Task SetCursorRectCore(PixelRect cursorRect) =>
- _context.SetCursorRectAsync(cursorRect.X, cursorRect.Y, Math.Max(1, cursorRect.Width),
- Math.Max(1, cursorRect.Height));
-
- protected override Task SetActiveCore(bool active)
- {
- if (active)
- return _context.FocusInAsync();
- else
- return _context.FocusOutAsync();
- }
+ _context?.SetCursorRectAsync(cursorRect.X, cursorRect.Y, Math.Max(1, cursorRect.Width),
+ Math.Max(1, cursorRect.Height))
+ ?? Task.CompletedTask;
+
+ protected override Task SetActiveCore(bool active)=> (active
+ ? _context?.FocusInAsync()
+ : _context?.FocusOutAsync())
+ ?? Task.CompletedTask;
+
- protected override Task ResetContextCore() => _context.ResetAsync();
+ protected override Task ResetContextCore() => _context?.ResetAsync()
+ ?? Task.CompletedTask;
protected override async Task HandleKeyCore(RawKeyEventArgs args, int keyVal, int keyCode)
{
@@ -88,9 +88,15 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
var type = args.Type == RawKeyEventType.KeyDown ?
FcitxKeyEventType.FCITX_PRESS_KEY :
FcitxKeyEventType.FCITX_RELEASE_KEY;
-
- return await _context.ProcessKeyEventAsync((uint)keyVal, (uint)keyCode, (uint)state, (int)type,
- (uint)args.Timestamp).ConfigureAwait(false);
+ if (_context is { })
+ {
+ return await _context.ProcessKeyEventAsync((uint)keyVal, (uint)keyCode, (uint)state, (int)type,
+ (uint)args.Timestamp).ConfigureAwait(false);
+ }
+ else
+ {
+ return false;
+ }
}
public override void SetOptions(TextInputOptions options) =>
diff --git a/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusDBus.cs b/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusDBus.cs
index 26c0d249f3..4ef034adb9 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusDBus.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusDBus.cs
@@ -22,25 +22,25 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
Task
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index ee4125101c..46a985c0e8 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -133,7 +133,7 @@ namespace Avalonia.LinuxFramebuffer.Output
var device = gbm_create_device(card.Fd);
_gbmTargetSurface = gbm_surface_create(device, modeInfo.Resolution.Width, modeInfo.Resolution.Height,
GbmColorFormats.GBM_FORMAT_XRGB8888, GbmBoFlags.GBM_BO_USE_SCANOUT | GbmBoFlags.GBM_BO_USE_RENDERING);
- if(_gbmTargetSurface == null)
+ if(_gbmTargetSurface == IntPtr.Zero)
throw new InvalidOperationException("Unable to create GBM surface");
_eglDisplay = new EglDisplay(new EglInterface(eglGetProcAddress), false, 0x31D7, device, null);
diff --git a/src/Avalonia.SourceGenerator/IsExternalInit.cs b/src/Shared/IsExternalInit.cs
similarity index 100%
rename from src/Avalonia.SourceGenerator/IsExternalInit.cs
rename to src/Shared/IsExternalInit.cs