Browse Source

Merge branch 'master' into dependabot/npm_and_yarn/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/terser-5.14.2

pull/8555/head
Benedikt Stebner 4 years ago
committed by GitHub
parent
commit
b56e7f61ca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Avalonia.sln
  2. 3
      src/Avalonia.FreeDesktop/DBusHelper.cs
  3. 33
      src/Avalonia.FreeDesktop/DBusSystemDialog.cs
  4. 64
      src/Avalonia.X11/NativeDialogs/CompositeStorageProvider.cs
  5. 2
      src/Avalonia.X11/NativeDialogs/Gtk.cs
  6. 30
      src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs
  7. 8
      src/Avalonia.X11/X11Platform.cs
  8. 9
      src/Avalonia.X11/X11Window.cs

1
Avalonia.sln

@ -559,6 +559,7 @@ Global
{2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A} SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

3
src/Avalonia.FreeDesktop/DBusHelper.cs

@ -24,8 +24,7 @@ namespace Avalonia.FreeDesktop
if (_ctx is not null) if (_ctx is not null)
_ctx?.Post(d, state); _ctx?.Post(d, state);
else else
lock (_lock) d(state);
d(state);
} }
} }

33
src/Avalonia.FreeDesktop/DBusSystemDialog.cs

@ -15,27 +15,26 @@ namespace Avalonia.FreeDesktop
{ {
internal class DBusSystemDialog : BclStorageProvider internal class DBusSystemDialog : BclStorageProvider
{ {
private static readonly Lazy<IFileChooser?> s_fileChooser = new(() => private static readonly Lazy<IFileChooser?> s_fileChooser = new(() => DBusHelper.Connection?
.CreateProxy<IFileChooser>("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"));
internal static async Task<IStorageProvider?> TryCreate(IPlatformHandle handle)
{ {
var fileChooser = DBusHelper.Connection?.CreateProxy<IFileChooser>("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"); if (handle.HandleDescriptor == "XID" && s_fileChooser.Value is { } fileChooser)
if (fileChooser is null)
return null;
try
{ {
_ = fileChooser.GetVersionAsync(); try
return fileChooser; {
} await fileChooser.GetVersionAsync();
catch (Exception e) return new DBusSystemDialog(fileChooser, handle);
{ }
Logger.TryGet(LogEventLevel.Error, LogArea.X11Platform)?.Log(null, $"Unable to connect to org.freedesktop.portal.Desktop: {e.Message}"); catch (Exception e)
return null; {
Logger.TryGet(LogEventLevel.Error, LogArea.X11Platform)?.Log(null, $"Unable to connect to org.freedesktop.portal.Desktop: {e.Message}");
return null;
}
} }
});
internal static DBusSystemDialog? TryCreate(IPlatformHandle handle) return null;
{
return handle.HandleDescriptor == "XID" && s_fileChooser.Value is { } fileChooser
? new DBusSystemDialog(fileChooser, handle) : null;
} }
private readonly IFileChooser _fileChooser; private readonly IFileChooser _fileChooser;

64
src/Avalonia.X11/NativeDialogs/CompositeStorageProvider.cs

@ -0,0 +1,64 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Platform.Storage;
namespace Avalonia.X11.NativeDialogs;
internal class CompositeStorageProvider : IStorageProvider
{
private readonly IEnumerable<Func<Task<IStorageProvider?>>> _factories;
public CompositeStorageProvider(IEnumerable<Func<Task<IStorageProvider?>>> factories)
{
_factories = factories;
}
public bool CanOpen => true;
public bool CanSave => true;
public bool CanPickFolder => true;
private async Task<IStorageProvider> EnsureStorageProvider()
{
foreach (var factory in _factories)
{
var provider = await factory();
if (provider is not null)
{
return provider;
}
}
throw new InvalidOperationException("Neither DBus nor GTK are available on the system");
}
public async Task<IReadOnlyList<IStorageFile>> OpenFilePickerAsync(FilePickerOpenOptions options)
{
var provider = await EnsureStorageProvider().ConfigureAwait(false);
return await provider.OpenFilePickerAsync(options).ConfigureAwait(false);
}
public async Task<IStorageFile?> SaveFilePickerAsync(FilePickerSaveOptions options)
{
var provider = await EnsureStorageProvider().ConfigureAwait(false);
return await provider.SaveFilePickerAsync(options).ConfigureAwait(false);
}
public async Task<IReadOnlyList<IStorageFolder>> OpenFolderPickerAsync(FolderPickerOpenOptions options)
{
var provider = await EnsureStorageProvider().ConfigureAwait(false);
return await provider.OpenFolderPickerAsync(options).ConfigureAwait(false);
}
public async Task<IStorageBookmarkFile?> OpenFileBookmarkAsync(string bookmark)
{
var provider = await EnsureStorageProvider().ConfigureAwait(false);
return await provider.OpenFileBookmarkAsync(bookmark).ConfigureAwait(false);
}
public async Task<IStorageBookmarkFolder?> OpenFolderBookmarkAsync(string bookmark)
{
var provider = await EnsureStorageProvider().ConfigureAwait(false);
return await provider.OpenFolderBookmarkAsync(bookmark).ConfigureAwait(false);
}
}

2
src/Avalonia.X11/NativeDialogs/Gtk.cs

@ -264,8 +264,6 @@ namespace Avalonia.X11.NativeDialogs
public static Task<bool> StartGtk() public static Task<bool> StartGtk()
{ {
return StartGtkCore(); return StartGtkCore();
lock (s_startGtkLock)
return s_startGtkTask ??= StartGtkCore();
} }
private static void GtkThread(TaskCompletionSource<bool> tcs) private static void GtkThread(TaskCompletionSource<bool> tcs)

30
src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs

@ -17,10 +17,10 @@ namespace Avalonia.X11.NativeDialogs
{ {
internal class GtkSystemDialog : BclStorageProvider internal class GtkSystemDialog : BclStorageProvider
{ {
private Task<bool>? _initialized; private static Task<bool>? _initialized;
private readonly X11Window _window; private readonly X11Window _window;
public GtkSystemDialog(X11Window window) private GtkSystemDialog(X11Window window)
{ {
_window = window; _window = window;
} }
@ -31,10 +31,15 @@ namespace Avalonia.X11.NativeDialogs
public override bool CanPickFolder => true; public override bool CanPickFolder => true;
public override async Task<IReadOnlyList<IStorageFile>> OpenFilePickerAsync(FilePickerOpenOptions options) internal static async Task<IStorageProvider?> TryCreate(X11Window window)
{ {
await EnsureInitialized(); _initialized ??= StartGtk();
return await _initialized ? new GtkSystemDialog(window) : null;
}
public override async Task<IReadOnlyList<IStorageFile>> OpenFilePickerAsync(FilePickerOpenOptions options)
{
return await await RunOnGlibThread(async () => return await await RunOnGlibThread(async () =>
{ {
var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.Open, var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.Open,
@ -46,8 +51,6 @@ namespace Avalonia.X11.NativeDialogs
public override async Task<IReadOnlyList<IStorageFolder>> OpenFolderPickerAsync(FolderPickerOpenOptions options) public override async Task<IReadOnlyList<IStorageFolder>> OpenFolderPickerAsync(FolderPickerOpenOptions options)
{ {
await EnsureInitialized();
return await await RunOnGlibThread(async () => return await await RunOnGlibThread(async () =>
{ {
var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.SelectFolder, var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.SelectFolder,
@ -59,8 +62,6 @@ namespace Avalonia.X11.NativeDialogs
public override async Task<IStorageFile?> SaveFilePickerAsync(FilePickerSaveOptions options) public override async Task<IStorageFile?> SaveFilePickerAsync(FilePickerSaveOptions options)
{ {
await EnsureInitialized();
return await await RunOnGlibThread(async () => return await await RunOnGlibThread(async () =>
{ {
var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.Save, var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.Save,
@ -225,19 +226,6 @@ namespace Avalonia.X11.NativeDialogs
return tcs.Task; return tcs.Task;
} }
private async Task EnsureInitialized()
{
if (_initialized == null)
{
_initialized = StartGtk();
}
if (!(await _initialized))
{
throw new Exception("Unable to initialize GTK on separate thread");
}
}
private static void UpdateParent(IntPtr chooser, IWindowImpl parentWindow) private static void UpdateParent(IntPtr chooser, IWindowImpl parentWindow)
{ {
var xid = parentWindow.Handle.Handle; var xid = parentWindow.Handle.Handle;

8
src/Avalonia.X11/X11Platform.cs

@ -216,16 +216,16 @@ namespace Avalonia
public bool OverlayPopups { get; set; } public bool OverlayPopups { get; set; }
/// <summary> /// <summary>
/// Enables native file dialogs as well as global menu support on Linux desktop environments where it's supported (e. g. XFCE and MATE with plugin, KDE, etc). /// Enables global menu support on Linux desktop environments where it's supported (e. g. XFCE and MATE with plugin, KDE, etc).
/// The default value is true. /// The default value is true.
/// </summary> /// </summary>
public bool UseDBusMenu { get; set; } = true; public bool UseDBusMenu { get; set; } = true;
/// <summary> /// <summary>
/// Enables GTK file picker instead of default FreeDesktop. /// Enables DBus file picker instead of GTK.
/// The default value is true. And FreeDesktop file picker is used instead if available. /// The default value is true.
/// </summary> /// </summary>
public bool UseGtkFilePicker { get; set; } = false; public bool UseDBusFilePicker { get; set; } = true;
/// <summary> /// <summary>
/// Deferred renderer would be used when set to true. Immediate renderer when set to false. The default value is true. /// Deferred renderer would be used when set to true. Immediate renderer when set to false. The default value is true.

9
src/Avalonia.X11/X11Window.cs

@ -22,6 +22,7 @@ using Avalonia.Rendering;
using Avalonia.Rendering.Composition; using Avalonia.Rendering.Composition;
using Avalonia.Threading; using Avalonia.Threading;
using Avalonia.X11.Glx; using Avalonia.X11.Glx;
using Avalonia.X11.NativeDialogs;
using static Avalonia.X11.XLib; using static Avalonia.X11.XLib;
// ReSharper disable IdentifierTypo // ReSharper disable IdentifierTypo
// ReSharper disable StringLiteralTypo // ReSharper disable StringLiteralTypo
@ -215,9 +216,11 @@ namespace Avalonia.X11
_x11.Atoms.XA_CARDINAL, 32, PropertyMode.Replace, ref _xSyncCounter, 1); _x11.Atoms.XA_CARDINAL, 32, PropertyMode.Replace, ref _xSyncCounter, 1);
} }
var canUseFreeDekstopPicker = !platform.Options.UseGtkFilePicker && platform.Options.UseDBusMenu; StorageProvider = new CompositeStorageProvider(new Func<Task<IStorageProvider>>[]
StorageProvider = canUseFreeDekstopPicker && DBusSystemDialog.TryCreate(Handle) is {} dBusStorage {
? dBusStorage : new NativeDialogs.GtkSystemDialog(this); () => _platform.Options.UseDBusFilePicker ? DBusSystemDialog.TryCreate(Handle) : Task.FromResult<IStorageProvider>(null),
() => GtkSystemDialog.TryCreate(this),
});
} }
class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo

Loading…
Cancel
Save