diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs index 59b320f5..383a770b 100644 --- a/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs +++ b/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs @@ -50,7 +50,7 @@ public IEnumerable AllChildren() where T : DisplayDevice } public DisplayDevice Parent { get; set; } - public IEnumerable Children => _children; + [DataMember] public IEnumerable Children => _children; /// /// Device name as returned by EnumDisplayDevices : diff --git a/LittleBigMouse.Core/LittleBigMouse.DisplayLayout/Monitors/IMonitorsLayout.cs b/LittleBigMouse.Core/LittleBigMouse.DisplayLayout/Monitors/IMonitorsLayout.cs index 438393e7..d38f982f 100644 --- a/LittleBigMouse.Core/LittleBigMouse.DisplayLayout/Monitors/IMonitorsLayout.cs +++ b/LittleBigMouse.Core/LittleBigMouse.DisplayLayout/Monitors/IMonitorsLayout.cs @@ -3,6 +3,7 @@ using LittleBigMouse.Zoning; using System; using System.Collections.ObjectModel; +using System.Threading.Tasks; namespace LittleBigMouse.DisplayLayout.Monitors; @@ -54,13 +55,16 @@ public interface IMonitorsLayout : IDisposable WinDef.DpiAwareness DpiAwareness { get; } PhysicalMonitor PrimaryMonitor { get; } - bool Enabled { get; } + bool Enabled { get; set; } bool AutoUpdate { get; } + bool LoadAtStartup { get; } ZonesLayout ComputeZones(); void Compact(); void ForceCompact(); void UpdatePhysicalMonitors(); + bool Schedule(); + void Unschedule(); } \ No newline at end of file diff --git a/LittleBigMouse.Daemon/LittleBigMouse.Hook/LittleBigMouse.Hook.cpp b/LittleBigMouse.Daemon/LittleBigMouse.Hook/LittleBigMouse.Hook.cpp index c6293fbf..aad8563a 100644 --- a/LittleBigMouse.Daemon/LittleBigMouse.Hook/LittleBigMouse.Hook.cpp +++ b/LittleBigMouse.Daemon/LittleBigMouse.Hook/LittleBigMouse.Hook.cpp @@ -66,7 +66,7 @@ static std::string getParentProcess() int main(int argc, char *argv[]){ - #if !defined(_DEBUG) + //#if !defined(_DEBUG) constexpr char szUniqueNamedMutex[] = "LittleBigMouse_Daemon"; HANDLE hHandle = CreateMutex(nullptr, TRUE, reinterpret_cast(szUniqueNamedMutex)); @@ -82,7 +82,8 @@ int main(int argc, char *argv[]){ return(1); // Exit program } - ShowWindow( GetConsoleWindow(), SW_HIDE ); + #if !defined(_DEBUG) + ShowWindow( GetConsoleWindow(), SW_HIDE ); #endif SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ); @@ -110,25 +111,23 @@ int main(int argc, char *argv[]){ if(uiMode) { #if defined(_DEBUG) - std::cout << "Starting in UI mode" << std::endl; + std::cout << "Starting in UI mode\n"; #endif LittleBigMouseDaemon( &server, &engine, &hook ).Run(""); } else { #if defined(_DEBUG) - std::cout << "Starting in Daemon mode" << std::endl; + std::cout << "Starting in Daemon mode\n"; #endif LittleBigMouseDaemon( &server, &engine, &hook ).Run(R"(\Mgth\LittleBigMouse\Current.xml)"); } - #if !defined(_DEBUG) if(hHandle) { ReleaseMutex (hHandle); CloseHandle (hHandle); } - #endif #if defined(_DEBUG) system("pause"); #endif diff --git a/LittleBigMouse.Setup/LittleBigMouse.nsi b/LittleBigMouse.Setup/LittleBigMouse.nsi index 0bb5f04e..9725b655 100644 --- a/LittleBigMouse.Setup/LittleBigMouse.nsi +++ b/LittleBigMouse.Setup/LittleBigMouse.nsi @@ -43,8 +43,8 @@ ;--------------------------------- ;General - !define MUI_ICON "${main}\MainIcon.ico" - !define MUI_UNICON "${main}\MainIcon.ico" + !define MUI_ICON "${main}\Assets\lbm-logo.ico" + !define MUI_UNICON "${main}\Assets\lbm-logo.ico" ; !define MUI_SPECIALBITMAP "Bitmap.bmp" ;-------------------------------- diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Assets/Icon/lbm_dead.svg b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Assets/Icon/lbm_dead.svg new file mode 100644 index 00000000..c24fd329 --- /dev/null +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Assets/Icon/lbm_dead.svg @@ -0,0 +1,221 @@ + +image/svg+xml diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Assets/lbm-logo.ico b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Assets/lbm-logo.ico new file mode 100644 index 00000000..b9fac54b Binary files /dev/null and b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Assets/lbm-logo.ico differ diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Controls/LocationControlView.axaml.cs b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Controls/LocationControlView.axaml.cs index 4eedba57..eab9aecd 100644 --- a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Controls/LocationControlView.axaml.cs +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Controls/LocationControlView.axaml.cs @@ -26,8 +26,15 @@ You should have received a copy of the GNU General Public License using HLab.Mvvm.Annotations; using LittleBigMouse.Plugins; using System; +using System.IO.Compression; +using System.IO; +using System.Text; using System.Text.Json.Nodes; using System.Threading.Tasks; +using Avalonia.Platform.Storage; +using System.Security.Cryptography.X509Certificates; +using Avalonia.Controls.Shapes; +using System.Diagnostics; namespace LittleBigMouse.Ui.Avalonia.Controls; @@ -45,7 +52,7 @@ public LocationControlView() private async void Button_Click(object? sender, RoutedEventArgs e) { - if(!(DataContext is LocationControlViewModel vm)) return; + if(DataContext is not LocationControlViewModel vm) return; var json = vm.Copy(); @@ -56,11 +63,55 @@ private async void Button_Click(object? sender, RoutedEventArgs e) { await clipboard.SetTextAsync(json); } + + var provider = TopLevel.GetTopLevel(this)?.StorageProvider; + if (provider == null) return; + + var folder = await provider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents); + var filename = "LittleBigMouse.Export.gz"; + + var result = await provider.SaveFilePickerAsync(new FilePickerSaveOptions{ + DefaultExtension = ".export.gz" , + SuggestedFileName = filename, + SuggestedStartLocation = folder + }); + + if(result!=null) + { + var path = result.TryGetLocalPath(); + if(path != null) + { + SaveConfig(json, path); + OpenExplorerWithSelectedFile(path); + } + } } catch (Exception ex) { } + } + + static void SaveConfig(string txt, string path) + { + byte[] donnees = Encoding.UTF8.GetBytes(txt); + + using FileStream fichierSortie = File.Create(path); + using GZipStream fluxGZip = new GZipStream(fichierSortie, CompressionMode.Compress); + fluxGZip.Write(donnees, 0, donnees.Length); } + + static void OpenExplorerWithSelectedFile(string filePath) + { + if (!string.IsNullOrEmpty(filePath)) + { + Process.Start("explorer.exe", $"/select,\"{filePath}\""); + } + else + { + Console.WriteLine("Invalid file path."); + } + } + } diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/LittleBigMouse.Ui.Avalonia.csproj b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/LittleBigMouse.Ui.Avalonia.csproj index ed83d262..032050c1 100644 --- a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/LittleBigMouse.Ui.Avalonia.csproj +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/LittleBigMouse.Ui.Avalonia.csproj @@ -4,7 +4,7 @@ enable x64;x86;AnyCPU WinExe - MainIcon.ico + Assets\lbm-logo.ico preview true Mathieu GRENET @@ -79,7 +79,7 @@ - + diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainService.cs b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainService.cs index 943d53f4..54d33b4b 100644 --- a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainService.cs +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainService.cs @@ -35,9 +35,11 @@ You should have received a copy of the GNU General Public License using LittleBigMouse.DisplayLayout; using LittleBigMouse.DisplayLayout.Monitors; using LittleBigMouse.Plugins; +using LittleBigMouse.Ui.Avalonia.Persistency; using LittleBigMouse.Ui.Avalonia.Updater; using LittleBigMouse.Zoning; using Live.Avalonia; +using ScottPlot; namespace LittleBigMouse.Ui.Avalonia.Main; @@ -135,7 +137,12 @@ public async Task StartNotifierAsync() await _notify.AddMenuAsync(-1, "Check for update","Icon/lbm_on", CheckUpdateAsync); await _notify.AddMenuAsync(-1, "Open","Icon/lbm_off", ShowControlAsync); await _notify.AddMenuAsync(-1, "Start","Icon/Start", StartAsync); - await _notify.AddMenuAsync(-1, "Stop","Icon/Stop", () => _littleBigMouseClientService.StopAsync()); + await _notify.AddMenuAsync(-1, "Stop","Icon/Stop", () => + { + MonitorsLayout.Enabled = false; + MonitorsLayout.SaveEnabled(); + return _littleBigMouseClientService.StopAsync(); + }); await _notify.AddMenuAsync(-1, "Exit", "Icon/sys/Close", QuitAsync); await _notify.SetIconAsync("Icon/lbm_off",128); diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainViewModel.cs b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainViewModel.cs index 562ca98e..6673a329 100644 --- a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainViewModel.cs +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Main/MainViewModel.cs @@ -21,7 +21,7 @@ namespace LittleBigMouse.Ui.Avalonia.Main; public class MainViewModel : ViewModel, IMainViewModel, IMainPluginsViewModel { public string Title => "Little Big Mouse"; - public object MainIcon { get; } = new WindowIcon(AssetLoader.Open(new Uri("avares://LittleBigMouse.Ui.Avalonia/Assets/MainIcon.ico"))); + public object MainIcon { get; } = new WindowIcon(AssetLoader.Open(new Uri("avares://LittleBigMouse.Ui.Avalonia/Assets/lbm-logo.ico"))); public MainViewModel(IIconService iconService, ILocalizationService localizationService) { diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Persistency/PersistencyExtentions.cs b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Persistency/PersistencyExtentions.cs index ff474ead..26c537b7 100644 --- a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Persistency/PersistencyExtentions.cs +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Persistency/PersistencyExtentions.cs @@ -66,7 +66,7 @@ public static void Load(this MonitorsLayout @this) } - public static bool SaveEnabled(this MonitorsLayout @this) + public static bool SaveEnabled(this IMonitorsLayout @this) { using var k = @this.OpenRegKey(true); if (k == null) return false; diff --git a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Program.cs b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Program.cs index f570929b..8a0a4847 100644 --- a/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Program.cs +++ b/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/Program.cs @@ -131,12 +131,20 @@ public static void UIMain(Application app, string[] args) var task = boot.BootAsync(); - // Once console Main is finished we cancel the token, so avalonia run loop will be stopped as well - //task.ContinueWith(_ => cts.Cancel()); - - app.Run(cts.Token); - - // Rethrow any exceptions from ConsoleMain - task.Wait(cts.Token); + try + { + app.Run(cts.Token); + } + catch(InvalidOperationException) + { + cts.Cancel(); + } + + try + { + task.Wait(cts.Token); + } + catch(OperationCanceledException) + { } } } \ No newline at end of file