From 61e4e50d3120b6ccac553f233cbdb65d7bce3882 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 6 Sep 2017 13:28:19 +0300 Subject: [PATCH 1/5] Enable win32 file dialog functionality for .NET Standard build --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 6 ++---- src/Windows/Avalonia.Win32/SystemDialogImpl.cs | 9 +-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 2d739f095d..e7401c19b9 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -841,14 +841,13 @@ namespace Avalonia.Win32.Interop return SetClassLong64(hWnd, nIndex, dwNewLong); } -#if !NETSTANDARD && !NETSTANDARD2_0 + [ComImport, ClassInterface(ClassInterfaceType.None), TypeLibType(TypeLibTypeFlags.FCanCreate), Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")] internal class FileOpenDialogRCW { } [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv); -#endif [DllImport("user32.dll", SetLastError = true)] public static extern bool OpenClipboard(IntPtr hWndOwner); @@ -1183,7 +1182,7 @@ namespace Avalonia.Win32.Interop public int flagsEx; } } -#if !NETSTANDARD && !NETSTANDARD1_3 + [ComImport(), Guid("42F85136-DB7E-439C-85F1-E4075D135FC8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IFileDialog { @@ -1283,5 +1282,4 @@ namespace Avalonia.Win32.Interop uint Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, [In] uint hint, out int piOrder); } -#endif } diff --git a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs index 4d8c375aaf..eef8a4d449 100644 --- a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs +++ b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs @@ -100,17 +100,14 @@ namespace Avalonia.Win32 var pofn = &ofn; // We should save the current directory to restore it later. -#if !NETSTANDARD var currentDirectory = Environment.CurrentDirectory; -#endif + var res = dialog is OpenFileDialog ? UnmanagedMethods.GetOpenFileName(new IntPtr(pofn)) : UnmanagedMethods.GetSaveFileName(new IntPtr(pofn)); // Restore the old current directory, since GetOpenFileName and GetSaveFileName change it after they're called -#if !NETSTANDARD Environment.CurrentDirectory = currentDirectory; -#endif if (!res) return null; @@ -155,9 +152,6 @@ namespace Avalonia.Win32 public Task ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) { -#if NETSTANDARD - throw new NotImplementedException(); -#else return Task.Factory.StartNew(() => { string result = string.Empty; @@ -214,7 +208,6 @@ namespace Avalonia.Win32 return result; }); -#endif } } } From f330132dc3232ebd914a29d095a9a44e9f1f45c5 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 6 Sep 2017 14:40:46 +0300 Subject: [PATCH 2/5] Use CoCreateInstance for .NET Core compatibility --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 5 +++-- src/Windows/Avalonia.Win32/SystemDialogImpl.cs | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index e7401c19b9..4fed7a34f4 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -842,8 +842,9 @@ namespace Avalonia.Win32.Interop return SetClassLong64(hWnd, nIndex, dwNewLong); } - [ComImport, ClassInterface(ClassInterfaceType.None), TypeLibType(TypeLibTypeFlags.FCanCreate), Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")] - internal class FileOpenDialogRCW { } + [DllImport("ole32.dll", PreserveSig = true)] + internal static extern int CoCreateInstance(ref Guid clsid, + IntPtr ignore1, int ignore2, ref Guid iid, [MarshalAs(UnmanagedType.IUnknown), Out] out object pUnkOuter); [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] diff --git a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs index eef8a4d449..e08fecbbd9 100644 --- a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs +++ b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs @@ -157,7 +157,11 @@ namespace Avalonia.Win32 string result = string.Empty; var hWnd = parent?.Handle?.Handle ?? IntPtr.Zero; - var frm = (IFileDialog)(new UnmanagedMethods.FileOpenDialogRCW()); + var clsid = Guid.Parse("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7"); + var iid = Guid.Parse("42F85136-DB7E-439C-85F1-E4075D135FC8"); + + UnmanagedMethods.CoCreateInstance(ref clsid, IntPtr.Zero, 1, ref iid, out var unk); + var frm = (IFileDialog)unk; uint options; frm.GetOptions(out options); options |= (uint)(UnmanagedMethods.FOS.FOS_PICKFOLDERS | UnmanagedMethods.FOS.FOS_FORCEFILESYSTEM | UnmanagedMethods.FOS.FOS_NOVALIDATE | UnmanagedMethods.FOS.FOS_NOTESTFILECREATE | UnmanagedMethods.FOS.FOS_DONTADDTORECENT); From 0a77519906faf8833792087d5300f1c8a8e76c8d Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 6 Sep 2017 17:09:07 +0300 Subject: [PATCH 3/5] Update build.md --- docs/guidelines/build.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/guidelines/build.md b/docs/guidelines/build.md index 822496814b..0cf91d913a 100644 --- a/docs/guidelines/build.md +++ b/docs/guidelines/build.md @@ -80,10 +80,11 @@ mono ./samples/ControlCatalog.Desktop/bin/Debug/ControlCatalog.Desktop.exe ### Building Avalonia in MonoDevelop -Unless you have a very current version of monodevelop (6.1.x or newer), it is necessary to manually -restore the Nuget depdendencies as [mentioned above](#restore-nuget-packages). You must then -disable MonoDevelop's inbuilt NuGet package manager add-in by going to `Tools -> Add-in Manager` or -it will complain that a newer version of NuGet is needed. +Flatpak version will *NOT* work. Version from https://github.com/cra0zy/monodevelop-run-installer/ might work if you are very lucky. Make sure that you have the latest version of Mono (from alpha update channel) and .NET Core SDK. Make sure to follow `FrameworkPathOverride` workaround from https://github.com/dotnet/sdk/issues/335 + +### Building and running Avalonia in Rider + +For Linux/OSX you'll probably need to apply workaround from https://github.com/dotnet/sdk/issues/335 + +Just add `export FrameworkPathOverride=/usr/lib/mono/4.6.1-api` (or `export FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api` for OSX) -Finally, select the `Debug | Mono` or `Release | Mono` build configuration and you should be good to -go! From d4048de9947ace1ca953670a555516f626bc4b4e Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 6 Sep 2017 15:58:28 +0300 Subject: [PATCH 4/5] Don't try to load library with path == null --- src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs index cf065b86dc..764cbfd6b6 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs @@ -104,14 +104,16 @@ namespace Avalonia.Gtk3.Interop var path = Custom?.Lookup(dll); if (path == null && Custom?.BasePath != null) path = Path.Combine(Custom.BasePath, name); - - try - { - return loader.LoadLibrary(path); - } - catch (Exception e) + if (path != null) { - exceptions.Add(e); + try + { + return loader.LoadLibrary(path); + } + catch (Exception e) + { + exceptions.Add(e); + } } throw new AggregateException("Unable to load " + dll, exceptions); } From b013caee699756394053328ed504799eb6b8ef97 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Wed, 6 Sep 2017 15:59:13 +0300 Subject: [PATCH 5/5] Add .idea to .gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 1d74816204..5fa78979c3 100644 --- a/.gitignore +++ b/.gitignore @@ -159,6 +159,12 @@ $RECYCLE.BIN/ *.userprefs *.nugetreferenceswitcher + +################# +## Rider +################# +.idea + ################# ## Cake #################