From a35efecb5ce1ed73c989f3b0472f4603923277ab Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Wed, 21 Aug 2019 18:43:41 +0800 Subject: [PATCH] Decouple platform specific implementations to their respective projects. Some refactoring. --- .../ManagedFileChooserSources.cs | 36 +-------- .../LinuxMountedVolumeInfoListener.cs | 23 ++---- .../LinuxMountedVolumeInfoProvider.cs | 2 +- src/Avalonia.FreeDesktop/NativeMethods.cs | 31 ++++++++ src/Avalonia.Native/AvaloniaNativePlatform.cs | 4 +- .../MacOSMountedVolumeInfoProvider.cs | 78 +++++++++++++++++++ src/Windows/Avalonia.Win32/Win32Platform.cs | 4 +- .../WindowsMountedVolumeInfoListener.cs | 71 +++++++++++++++++ .../WindowsMountedVolumeInfoProvider.cs | 15 ++++ 9 files changed, 209 insertions(+), 55 deletions(-) create mode 100644 src/Avalonia.FreeDesktop/NativeMethods.cs create mode 100644 src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs create mode 100644 src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs create mode 100644 src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs diff --git a/src/Avalonia.Dialogs/ManagedFileChooserSources.cs b/src/Avalonia.Dialogs/ManagedFileChooserSources.cs index 981f7a7676..0dc024c4dd 100644 --- a/src/Avalonia.Dialogs/ManagedFileChooserSources.cs +++ b/src/Avalonia.Dialogs/ManagedFileChooserSources.cs @@ -53,44 +53,15 @@ namespace Avalonia.Dialogs public static ManagedFileChooserNavigationItem[] DefaultGetFileSystemRoots() { - // if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - // { - // return DriveInfo.GetDrives().Select(d => new ManagedFileChooserNavigationItem - // { - // ItemType = ManagedFileChooserItemType.Volume, - // DisplayName = d.Name, - // Path = d.RootDirectory.FullName - // }).ToArray(); - // } - // else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - // { - // var paths = Directory.GetDirectories("/Volumes"); - - // return paths.Select(x => new ManagedFileChooserNavigationItem - // { - // ItemType = ManagedFileChooserItemType.Volume, - // DisplayName = Path.GetFileName(x), - // Path = x - // }).ToArray(); - // } - // else - // { return MountedVolumes .Select(x => { var displayName = x.VolumeLabel; - if (displayName == null) + if (displayName == null & x.VolumeSizeBytes > 0) { - if (x.VolumePath == "/") - { - displayName = "File System"; - } - else if (x.VolumeSizeBytes > 0) - { - displayName = $"{ByteSizeHelper.ToString(x.VolumeSizeBytes)} Volume"; - }; - } + displayName = $"{ByteSizeHelper.ToString(x.VolumeSizeBytes)} Volume"; + }; try { @@ -110,7 +81,6 @@ namespace Avalonia.Dialogs }) .Where(x => x != null) .ToArray(); - // } } } } diff --git a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs index cb1ce9b410..8081528e55 100644 --- a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs +++ b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs @@ -10,27 +10,13 @@ using System.Text.RegularExpressions; using System.Runtime.InteropServices; using System.Text; -namespace Avalonia.FreeDesktop.Dbus +namespace Avalonia.FreeDesktop { internal class LinuxMountedVolumeInfoListener : IDisposable { private const string DevByLabelDir = "/dev/disk/by-label/"; private const string ProcPartitionsDir = "/proc/partitions"; private const string ProcMountsDir = "/proc/mounts"; - - [DllImport("libc", SetLastError = true)] - private static extern long readlink([MarshalAs(UnmanagedType.LPArray)] - byte[] filename, [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, long buflen); - - private string ReadLink(string path) - { - var symlink = Encoding.UTF8.GetBytes(path); - var results = new byte[4095]; - readlink(symlink, results, results.Length); - var rawstr = Encoding.UTF8.GetString(results); - return rawstr.Substring(0, rawstr.IndexOf('\0')); ; - } - private CompositeDisposable _disposables; private ObservableCollection _targetObs; private bool _beenDisposed = false; @@ -40,7 +26,7 @@ namespace Avalonia.FreeDesktop.Dbus _disposables = new CompositeDisposable(); this._targetObs = target; - var pollTimer = Observable.Interval(TimeSpan.FromSeconds(2)) + var pollTimer = Observable.Interval(TimeSpan.FromSeconds(1)) .Subscribe(Poll); _disposables.Add(pollTimer); @@ -48,7 +34,7 @@ namespace Avalonia.FreeDesktop.Dbus Poll(0); } - private string GetSymlinkTarget(string x) => Path.GetFullPath(Path.Combine(DevByLabelDir, ReadLink(x))); + private string GetSymlinkTarget(string x) => Path.GetFullPath(Path.Combine(DevByLabelDir, NativeMethods.ReadLink(x))); private void Poll(long _) { @@ -82,7 +68,8 @@ namespace Avalonia.FreeDesktop.Dbus var mountVolInfos = q1.ToArray(); - if (_targetObs.SequenceEqual(mountVolInfos)) return; + if (_targetObs.SequenceEqual(mountVolInfos)) + return; else { _targetObs.Clear(); diff --git a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs index 0d965a7dfc..d68c02bfd6 100644 --- a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs +++ b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoProvider.cs @@ -3,7 +3,7 @@ using System.Collections.ObjectModel; using Avalonia.Controls.Platform; -namespace Avalonia.FreeDesktop.Dbus +namespace Avalonia.FreeDesktop { public class LinuxMountedVolumeInfoProvider : IMountedVolumeInfoProvider { diff --git a/src/Avalonia.FreeDesktop/NativeMethods.cs b/src/Avalonia.FreeDesktop/NativeMethods.cs new file mode 100644 index 0000000000..d9b6dce082 --- /dev/null +++ b/src/Avalonia.FreeDesktop/NativeMethods.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Avalonia.Controls.Platform; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Text.RegularExpressions; +using System.Runtime.InteropServices; +using System.Text; + +namespace Avalonia.FreeDesktop +{ + internal static class NativeMethods + { + [DllImport("libc", SetLastError = true)] + private static extern long readlink([MarshalAs(UnmanagedType.LPArray)] byte[] filename, + [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, + long len); + + public static string ReadLink(string path) + { + var symlink = Encoding.UTF8.GetBytes(path); + var result = new byte[4095]; + readlink(symlink, result, result.Length); + var rawstr = Encoding.UTF8.GetString(result); + return rawstr.Substring(0, rawstr.IndexOf('\0')); + } + } +} diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index edde2176bd..0da97b915c 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -84,8 +84,8 @@ namespace Avalonia.Native .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())) .Bind().ToConstant(new GlPlatformFeature(_factory.ObtainGlFeature())) - .Bind() - .ToConstant(new PlatformHotkeyConfiguration(InputModifiers.Windows)); + .Bind().ToConstant(new PlatformHotkeyConfiguration(InputModifiers.Windows)) + .Bind().ToConstant(new MacOSMountedVolumeInfoProvider()); } public IWindowImpl CreateWindow() diff --git a/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs b/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs new file mode 100644 index 0000000000..eea695d77e --- /dev/null +++ b/src/Avalonia.Native/MacOSMountedVolumeInfoProvider.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Avalonia.Controls.Platform; + +namespace Avalonia.Native +{ + internal class WindowsMountedVolumeInfoListener : IDisposable + { + private readonly CompositeDisposable _disposables; + private readonly ObservableCollection _targetObs; + private bool _beenDisposed = false; + private ObservableCollection mountedDrives; + + public WindowsMountedVolumeInfoListener(ObservableCollection mountedDrives) + { + this.mountedDrives = mountedDrives; + _disposables = new CompositeDisposable(); + + var pollTimer = Observable.Interval(TimeSpan.FromSeconds(1)) + .Subscribe(Poll); + + _disposables.Add(pollTimer); + + Poll(0); + } + + private void Poll(long _) + { + var mountVolInfos = Directory.GetDirectories("/Volumes") + .Select(p => new MountedVolumeInfo() + { + VolumeLabel = Path.GetFileName(p), + VolumePath = p, + VolumeSizeBytes = 0 + }) + .ToArray(); + + if (_targetObs.SequenceEqual(mountVolInfos)) + return; + else + { + _targetObs.Clear(); + + foreach (var i in mountVolInfos) + _targetObs.Add(i); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!_beenDisposed) + { + if (disposing) + { + + } + _beenDisposed = true; + } + } + public void Dispose() + { + Dispose(true); + } + } + + public class MacOSMountedVolumeInfoProvider : IMountedVolumeInfoProvider + { + public IDisposable Listen(ObservableCollection mountedDrives) + { + Contract.Requires(mountedDrives != null); + return new WindowsMountedVolumeInfoListener(mountedDrives); + } + } +} diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index bc40ec2ff7..ac3fa021f1 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -90,7 +90,9 @@ namespace Avalonia.Win32 .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToSingleton() - .Bind().ToConstant(s_instance); + .Bind().ToConstant(s_instance) + .Bind().ToConstant(new WindowsMountedVolumeInfoProvider()); + if (options.AllowEglInitialization) Win32GlManager.Initialize(); diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs new file mode 100644 index 0000000000..3e2941814f --- /dev/null +++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Avalonia.Controls.Platform; + +namespace Avalonia.Win32 +{ + internal class WindowsMountedVolumeInfoListener : IDisposable + { + private readonly CompositeDisposable _disposables; + private readonly ObservableCollection _targetObs; + private bool _beenDisposed = false; + private ObservableCollection mountedDrives; + + public WindowsMountedVolumeInfoListener(ObservableCollection mountedDrives) + { + this.mountedDrives = mountedDrives; + _disposables = new CompositeDisposable(); + + var pollTimer = Observable.Interval(TimeSpan.FromSeconds(1)) + .Subscribe(Poll); + + _disposables.Add(pollTimer); + + Poll(0); + } + + private void Poll(long _) + { + var allDrives = DriveInfo.GetDrives(); + + var mountVolInfos = allDrives + .Select(p => new MountedVolumeInfo() + { + VolumeLabel = p.VolumeLabel, + VolumePath = p.RootDirectory.FullName, + VolumeSizeBytes = (ulong)p.TotalSize + }) + .ToArray(); + + if (_targetObs.SequenceEqual(mountVolInfos)) + return; + else + { + _targetObs.Clear(); + + foreach (var i in mountVolInfos) + _targetObs.Add(i); + } + } + + protected virtual void Dispose(bool disposing) + { + if (!_beenDisposed) + { + if (disposing) + { + + } + _beenDisposed = true; + } + } + public void Dispose() + { + Dispose(true); + } + } +} diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs new file mode 100644 index 0000000000..e1b5f5a3a0 --- /dev/null +++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.ObjectModel; +using Avalonia.Controls.Platform; + +namespace Avalonia.Win32 +{ + public class WindowsMountedVolumeInfoProvider : IMountedVolumeInfoProvider + { + public IDisposable Listen(ObservableCollection mountedDrives) + { + Contract.Requires(mountedDrives != null); + return new WindowsMountedVolumeInfoListener(mountedDrives); + } + } +}