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}
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

3
src/Avalonia.FreeDesktop/DBusHelper.cs

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

33
src/Avalonia.FreeDesktop/DBusSystemDialog.cs

@ -15,27 +15,26 @@ namespace Avalonia.FreeDesktop
{
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 (fileChooser is null)
return null;
try
if (handle.HandleDescriptor == "XID" && s_fileChooser.Value is { } fileChooser)
{
_ = fileChooser.GetVersionAsync();
return fileChooser;
}
catch (Exception e)
{
Logger.TryGet(LogEventLevel.Error, LogArea.X11Platform)?.Log(null, $"Unable to connect to org.freedesktop.portal.Desktop: {e.Message}");
return null;
try
{
await fileChooser.GetVersionAsync();
return new DBusSystemDialog(fileChooser, handle);
}
catch (Exception e)
{
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 handle.HandleDescriptor == "XID" && s_fileChooser.Value is { } fileChooser
? new DBusSystemDialog(fileChooser, handle) : null;
return null;
}
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()
{
return StartGtkCore();
lock (s_startGtkLock)
return s_startGtkTask ??= StartGtkCore();
}
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
{
private Task<bool>? _initialized;
private static Task<bool>? _initialized;
private readonly X11Window _window;
public GtkSystemDialog(X11Window window)
private GtkSystemDialog(X11Window window)
{
_window = window;
}
@ -31,10 +31,15 @@ namespace Avalonia.X11.NativeDialogs
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 () =>
{
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)
{
await EnsureInitialized();
return await await RunOnGlibThread(async () =>
{
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)
{
await EnsureInitialized();
return await await RunOnGlibThread(async () =>
{
var res = await ShowDialog(options.Title, _window, GtkFileChooserAction.Save,
@ -225,19 +226,6 @@ namespace Avalonia.X11.NativeDialogs
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)
{
var xid = parentWindow.Handle.Handle;

8
src/Avalonia.X11/X11Platform.cs

@ -216,16 +216,16 @@ namespace Avalonia
public bool OverlayPopups { get; set; }
/// <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.
/// </summary>
public bool UseDBusMenu { get; set; } = true;
/// <summary>
/// Enables GTK file picker instead of default FreeDesktop.
/// The default value is true. And FreeDesktop file picker is used instead if available.
/// Enables DBus file picker instead of GTK.
/// The default value is true.
/// </summary>
public bool UseGtkFilePicker { get; set; } = false;
public bool UseDBusFilePicker { get; set; } = true;
/// <summary>
/// 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.Threading;
using Avalonia.X11.Glx;
using Avalonia.X11.NativeDialogs;
using static Avalonia.X11.XLib;
// ReSharper disable IdentifierTypo
// ReSharper disable StringLiteralTypo
@ -215,9 +216,11 @@ namespace Avalonia.X11
_x11.Atoms.XA_CARDINAL, 32, PropertyMode.Replace, ref _xSyncCounter, 1);
}
var canUseFreeDekstopPicker = !platform.Options.UseGtkFilePicker && platform.Options.UseDBusMenu;
StorageProvider = canUseFreeDekstopPicker && DBusSystemDialog.TryCreate(Handle) is {} dBusStorage
? dBusStorage : new NativeDialogs.GtkSystemDialog(this);
StorageProvider = new CompositeStorageProvider(new Func<Task<IStorageProvider>>[]
{
() => _platform.Options.UseDBusFilePicker ? DBusSystemDialog.TryCreate(Handle) : Task.FromResult<IStorageProvider>(null),
() => GtkSystemDialog.TryCreate(this),
});
}
class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo

Loading…
Cancel
Save