Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
771 changes: 771 additions & 0 deletions Avalonia.sln

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/Avalonia.DBus/Avalonia.DBus.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(AvsCurrentTargetFramework);$(AvsLegacyTargetFrameworks)</TargetFrameworks>
<DefineConstants Condition="'$(AvDBusInternal)' == 'true'">$(DefineConstants);AVDBUS_INTERNAL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<AvDBusInternal>true</AvDBusInternal>
<AvDBusSourcePath>../../external/Avalonia.DBus/src/Avalonia.DBus</AvDBusSourcePath>
</PropertyGroup>

<Import Project="../../build/NullableEnable.props" />
<Import Project="../../build/DevAnalyzers.props" />
<Import Project="../../build/TrimmingEnable.props" />

<ItemGroup>
<Compile Include="$(AvDBusSourcePath)/**/*.cs"
Exclude="$(AvDBusSourcePath)/obj/**/*.cs"
LinkBase="Avalonia.DBus" />
</ItemGroup>

</Project>
20 changes: 11 additions & 9 deletions src/Avalonia.FreeDesktop.AtSpi/Avalonia.FreeDesktop.AtSpi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,32 @@

<PropertyGroup>
<TargetFrameworks>$(AvsCurrentTargetFramework);$(AvsLegacyTargetFrameworks)</TargetFrameworks>
<DefineConstants>$(DefineConstants);AVDBUS_INTERNAL</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
<AvDBusInternal>true</AvDBusInternal>
<AvDBusSourcePath>../../external/Avalonia.DBus/src/Avalonia.DBus</AvDBusSourcePath>
</PropertyGroup>

<Import Project="../../build/NullableEnable.props" />
<Import Project="../../build/DevAnalyzers.props" />
<Import Project="../../build/TrimmingEnable.props" />

<Import Project="../tools/Avalonia.DBus.Generators/Avalonia.DBus.Generators.props" />

<PropertyGroup>
<DefineConstants>$(DefineConstants);AVDBUS_INTERNAL</DefineConstants>
<AvDBusInternal>true</AvDBusInternal>
</PropertyGroup>

<ItemGroup>
<Compile Include="$(AvDBusSourcePath)/**/*.cs"
Exclude="$(AvDBusSourcePath)/obj/**/*.cs"
LinkBase="Avalonia.DBus" />
<Compile Include="../Avalonia.Controls/Utils/StringUtils.cs">
<Link>Shared/StringUtils.cs</Link>
</Compile>
</Compile>
<ProjectReference Include="..\Avalonia.DBus\Avalonia.DBus.csproj" />
<ProjectReference Include="../tools/Avalonia.DBus.Generators/Avalonia.DBus.Generators.csproj"
OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../../packages/Avalonia/Avalonia.csproj" />
<ProjectReference Include="../tools/Avalonia.DBus.Generators/Avalonia.DBus.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
</ItemGroup>
Expand Down
20 changes: 16 additions & 4 deletions src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@

<Import Project="../../build/TrimmingEnable.props" />

<Import Project="../tools/Avalonia.DBus.Generators/Avalonia.DBus.Generators.props" />

<PropertyGroup>
<DefineConstants>$(DefineConstants);AVDBUS_INTERNAL</DefineConstants>
<AvDBusInternal>true</AvDBusInternal>
</PropertyGroup>

<ItemGroup>
<Compile Include="../Shared/IsExternalInit.cs" Link="IsExternalInit.cs" />
<Compile Include="../Avalonia.Controls/Utils/StringUtils.cs">
<Link>Shared/StringUtils.cs</Link>
</Compile>
<ProjectReference Include="..\Avalonia.DBus\Avalonia.DBus.csproj" />
<ProjectReference Include="../tools/Avalonia.DBus.Generators/Avalonia.DBus.Generators.csproj"
OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Tmds.DBus.Protocol" />
<PackageReference Include="Tmds.DBus.SourceGenerator" PrivateAssets="all" />
<Compile Include="../Shared/IsExternalInit.cs" Link="IsExternalInit.cs" />
</ItemGroup>

<ItemGroup>
Expand All @@ -27,6 +38,7 @@
</ItemGroup>

<ItemGroup>
<AdditionalFiles Include="DBusXml/Types.xml" />
<AdditionalFiles Include="DBusXml/com.canonical.AppMenu.Registrar.xml" DBusGeneratorMode="Proxy" />
<AdditionalFiles Include="DBusXml/com.canonical.dbusmenu.xml" DBusGeneratorMode="Handler" />

Expand Down
30 changes: 13 additions & 17 deletions src/Avalonia.FreeDesktop/DBusHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,46 @@
using System;
using System.Threading;
using Avalonia.Logging;
using Tmds.DBus.Protocol;
using Avalonia.DBus;

namespace Avalonia.FreeDesktop
{
internal static class DBusHelper
{
private static Connection? s_defaultConntection;
private static bool s_defaultConnectionFailed;
public static Connection? DefaultConnection
public static DBusConnection? DefaultConnection
{
get
{
if (s_defaultConntection == null && !s_defaultConnectionFailed)
if (field == null && !s_defaultConnectionFailed)
{
s_defaultConntection = TryCreateNewConnection();
if (s_defaultConntection == null)
field = TryCreateNewConnection();
if (field == null)
s_defaultConnectionFailed = true;
}

return s_defaultConntection;
return field;
}
}

public static Connection? TryCreateNewConnection(string? dbusAddress = null)
public static DBusConnection? TryCreateNewConnection(string? dbusAddress = null)
{
var oldContext = SynchronizationContext.Current;
Connection? conn = null;
DBusConnection? conn = null;
try
{
SynchronizationContext.SetSynchronizationContext(null);
conn = new Connection(new ClientConnectionOptions(dbusAddress ?? Address.Session!)
{
AutoConnect = false,
});

// Connect synchronously
conn.ConnectAsync().GetAwaiter().GetResult();
if (dbusAddress != null)
conn = DBusConnection.ConnectAsync(dbusAddress).GetAwaiter().GetResult();
else
conn = DBusConnection.ConnectSessionAsync().GetAwaiter().GetResult();
return conn;
}
catch (Exception e)
{
Logger.TryGet(LogEventLevel.Error, "DBUS")
?.Log(null, "Unable to connect to DBus: " + e);
conn?.Dispose();
conn?.DisposeAsync().AsTask().GetAwaiter().GetResult();
}
finally
{
Expand Down
28 changes: 12 additions & 16 deletions src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Avalonia.DBus;
using Avalonia.FreeDesktop.DBusXml;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Logging;
using Tmds.DBus.Protocol;
using Tmds.DBus.SourceGenerator;

namespace Avalonia.FreeDesktop.DBusIme
{
Expand All @@ -32,7 +32,7 @@ internal abstract class DBusTextInputMethodBase : IX11InputMethodControl, ITextI
{
private List<IDisposable> _disposables = new List<IDisposable>();
private Queue<string> _onlineNamesQueue = new Queue<string>();
protected Connection Connection { get; }
protected DBusConnection Connection { get; }
private readonly string[] _knownNames;
private bool _connecting;
private string? _currentName;
Expand All @@ -47,7 +47,7 @@ internal abstract class DBusTextInputMethodBase : IX11InputMethodControl, ITextI

protected bool IsConnected => _currentName != null;

public DBusTextInputMethodBase(Connection connection, params string[] knownNames)
public DBusTextInputMethodBase(DBusConnection connection, params string[] knownNames)
{
_queue = new DBusCallQueue(QueueOnErrorAsync);
Connection = connection;
Expand All @@ -61,7 +61,7 @@ public DBusTextInputMethodBase(Connection connection, params string[] knownNames

private async Task WatchAsync()
{
var dbus = new OrgFreedesktopDBusProxy(Connection, "org.freedesktop.DBus", "/org/freedesktop/DBus");
var dbus = new OrgFreedesktopDBusProxy(Connection, "org.freedesktop.DBus", new DBusObjectPath("/org/freedesktop/DBus"));
try
{
_disposables.Add(await dbus.WatchNameOwnerChangedAsync(OnNameChange));
Expand All @@ -75,7 +75,7 @@ private async Task WatchAsync()
try
{
var nameOwner = await dbus.GetNameOwnerAsync(name);
OnNameChange(null, (name, null, nameOwner));
OnNameChange(name, "", nameOwner);
}
catch (DBusException e)
{
Expand All @@ -89,22 +89,18 @@ private async Task WatchAsync()
protected string GetAppName() =>
Application.Current?.Name ?? Assembly.GetEntryAssembly()?.GetName()?.Name ?? "Avalonia";

private async void OnNameChange(Exception? e, (string ServiceName, string? OldOwner, string? NewOwner) args)
private async void OnNameChange(string serviceName, string oldOwner, string newOwner)
{
if (e is not null)
if (!_knownNames.Contains(serviceName))
{
Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, $"OnNameChange failed: {e}");
return;
}

if (!_knownNames.Contains(args.ServiceName))
{
return;
}
var newOwnerOrNull = string.IsNullOrEmpty(newOwner) ? null : newOwner;

if (args.NewOwner is not null && _currentName is null)
if (newOwnerOrNull is not null && _currentName is null)
{
_onlineNamesQueue.Enqueue(args.ServiceName);
_onlineNamesQueue.Enqueue(serviceName);
if (!_connecting)
{
_connecting = true;
Expand Down Expand Up @@ -138,7 +134,7 @@ private async void OnNameChange(Exception? e, (string ServiceName, string? OldOw
}

// IME has crashed
if (args.NewOwner is null && args.ServiceName == _currentName)
if (newOwnerOrNull is null && serviceName == _currentName)
{
_currentName = null;
foreach (var s in _disposables)
Expand Down
26 changes: 14 additions & 12 deletions src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.DBus;
using Avalonia.FreeDesktop.DBusXml;
using Avalonia.Reactive;
using Tmds.DBus.SourceGenerator;

namespace Avalonia.FreeDesktop.DBusIme.Fcitx
{
Expand Down Expand Up @@ -38,23 +40,23 @@ public async Task<bool> ProcessKeyEventAsync(uint keyVal, uint keyCode, uint sta
return await (_modern?.ProcessKeyEventAsync(keyVal, keyCode, state, type > 0, time) ?? Task.FromResult(false));
}

public ValueTask<IDisposable> WatchCommitStringAsync(Action<Exception?, string> handler) =>
public Task<IDisposable> WatchCommitStringAsync(Action<string> handler) =>
_old?.WatchCommitStringAsync(handler)
?? _modern?.WatchCommitStringAsync(handler)
?? new ValueTask<IDisposable>(Disposable.Empty);
?? Task.FromResult(Disposable.Empty);

public ValueTask<IDisposable> WatchForwardKeyAsync(Action<Exception?, (uint keyval, uint state, int type)> handler) =>
public Task<IDisposable> WatchForwardKeyAsync(Action<uint, uint, int> handler) =>
_old?.WatchForwardKeyAsync(handler)
?? _modern?.WatchForwardKeyAsync((e, ev) => handler.Invoke(e, (ev.Keyval, ev.State, ev.Type ? 1 : 0)))
?? new ValueTask<IDisposable>(Disposable.Empty);
?? _modern?.WatchForwardKeyAsync((keyval, state, type) => handler.Invoke(keyval, state, type ? 1 : 0))
?? Task.FromResult(Disposable.Empty);

public ValueTask<IDisposable> WatchUpdateFormattedPreeditAsync(
Action<Exception?, ((string?, int)[]? str, int cursorpos)> handler) =>
_old?.WatchUpdateFormattedPreeditAsync(handler!)
?? _modern?.WatchUpdateFormattedPreeditAsync(handler!)
?? new ValueTask<IDisposable>(Disposable.Empty);
public Task<IDisposable> WatchUpdateFormattedPreeditAsync(
Action<List<FormattedPreeditSegment>, int> handler) =>
_old?.WatchUpdateFormattedPreeditAsync(handler)
?? _modern?.WatchUpdateFormattedPreeditAsync(handler)
?? Task.FromResult(Disposable.Empty);

public Task SetCapacityAsync(uint flags) =>
_old?.SetCapacityAsync(flags) ?? _modern?.SetCapabilityAsync(flags) ?? Task.CompletedTask;
_old?.SetCapacityAsync(flags) ?? _modern?.SetCapabilityAsync((ulong)flags) ?? Task.CompletedTask;
}
}
Loading
Loading