From 89be43e15d028f80df6e4a69323f4d50c265e7f1 Mon Sep 17 00:00:00 2001 From: Laszlo Nemeth <57342539+donlaci@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:17:54 +0100 Subject: [PATCH 001/103] [Workspaces] implement the move feature (#35480) * [Workspaces] Add move functionality * spell checker * [Workspaces] Modify Arranger to move apps without launch * moved ipc helper * removed callback * use LauncherStatus in WindowArranger * wait for launching next app * launch in a separate thread and protect by mutexes * update app version in advance * changed canceling launch * increased waiting time * Fix optional parameter load from json * changed arranger waiting time * additional waiting time for Outlook * added app id * ensure ids before launch * set id in editor * minor updates * [Workspaces] Move: Get the nearest window when moving a window * [Workspaces] convert optional boolean to enum to avoid json problems * Handle case when the new Application Property "moveIfExists" does not exist * Re-implementing app-window pairing for moving feature. * spell checker * XAML formatting * Fixing bug: IPC message not arriving * spell checker * Removing app-level-setting for move app. Also fixed compiler errors due styling. * Updating editor window layout * Re-implementing window positioning UI elements * XAML formatting * Code review findings * Code cleanup * Code cleanup * Code cleanup * code cleanup * Code cleanup * Code cleanup * fix Move attribute after launch and snapshot * Extend WindowArranger with PWA functionality to detect different PWA apps. PwaHelper moved to the common library * fix repeat counter in the editor * Code optimization * code cleanup, optimization * fix double-processing window --------- Co-authored-by: Seraphima Co-authored-by: donlaci --- src/common/Display/dpi_aware.cpp | 18 ++ src/common/Display/dpi_aware.h | 1 + .../WorkspacesEditor/Data/ProjectData.cs | 3 - .../WorkspacesEditor/Data/TempProjectData.cs | 8 +- .../WorkspacesEditor/Data/WorkspacesData.cs | 10 +- .../Data/WorkspacesEditorData`1.cs | 16 +- .../WorkspacesEditor/MainWindow.xaml | 2 +- .../Models/AppListDataTemplateSelector.cs | 9 +- .../WorkspacesEditor/Models/Application.cs | 76 ++---- .../WorkspacesEditor/Models/Monitor.cs | 24 +- .../WorkspacesEditor/Models/MonitorSetup.cs | 4 +- .../WorkspacesEditor/Models/Project.cs | 74 +++--- .../Properties/Resources.Designer.cs | 47 ++-- .../Properties/Resources.resx | 11 +- .../WorkspacesEditor/Utils/DrawHelper.cs | 105 ++++----- .../WorkspacesEditor/Utils/IOUtils.cs | 14 +- .../WorkspacesEditor/Utils/MonitorHelper.cs | 10 +- .../WorkspacesEditor/Utils/ParsingResult.cs | 15 +- .../WorkspacesEditor/Utils/Settings.cs | 4 +- .../WorkspacesEditor/Utils/StringUtils.cs | 9 +- .../Utils/WorkspacesEditorIO.cs | 30 +-- .../WorkspacesEditorPage.xaml | 170 +++++++------- .../WorkspacesEditorPage.xaml.cs | 14 -- .../WorkspacesLauncher/Launcher.cpp | 4 +- .../Workspaces/WorkspacesLib/AppUtils.cpp | 19 +- .../Workspaces/WorkspacesLib/AppUtils.h | 4 + .../PwaHelper.cpp | 158 ++++++++----- .../Workspaces/WorkspacesLib/PwaHelper.h | 29 +++ .../WorkspacesLib/WorkspacesData.cpp | 2 +- .../WorkspacesLib/WorkspacesLib.vcxproj | 4 + .../WorkspacesLib.vcxproj.filters | 6 + .../Workspaces/WorkspacesLib/packages.config | 1 + .../WorkspacesSnapshotTool/PwaHelper.h | 20 -- .../WorkspacesSnapshotTool/SnapshotUtils.cpp | 62 +---- .../WorkspacesSnapshotTool.vcxproj | 2 - .../WorkspacesSnapshotTool.vcxproj.filters | 6 - .../WindowArranger.cpp | 222 +++++++++++++++--- .../WorkspacesWindowArranger/WindowArranger.h | 11 +- 38 files changed, 668 insertions(+), 556 deletions(-) rename src/modules/Workspaces/{WorkspacesSnapshotTool => WorkspacesLib}/PwaHelper.cpp (73%) create mode 100644 src/modules/Workspaces/WorkspacesLib/PwaHelper.h delete mode 100644 src/modules/Workspaces/WorkspacesSnapshotTool/PwaHelper.h diff --git a/src/common/Display/dpi_aware.cpp b/src/common/Display/dpi_aware.cpp index 8397430c6d03..cb8c46df3551 100644 --- a/src/common/Display/dpi_aware.cpp +++ b/src/common/Display/dpi_aware.cpp @@ -109,6 +109,24 @@ namespace DPIAware } } + void InverseConvert(HMONITOR monitor_handle, RECT& rect) + { + if (monitor_handle == NULL) + { + const POINT ptZero = { 0, 0 }; + monitor_handle = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY); + } + + UINT dpi_x, dpi_y; + if (GetDpiForMonitor(monitor_handle, MDT_EFFECTIVE_DPI, &dpi_x, &dpi_y) == S_OK) + { + rect.left = static_cast(std::round(rect.left * static_cast(DEFAULT_DPI) / dpi_x)); + rect.right = static_cast(std::round(rect.right * static_cast(DEFAULT_DPI) / dpi_x)); + rect.top = static_cast(std::round(rect.top * static_cast(DEFAULT_DPI) / dpi_y)); + rect.bottom = static_cast(std::round(rect.bottom * static_cast(DEFAULT_DPI) / dpi_y)); + } + } + void EnableDPIAwarenessForThisProcess() { SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); diff --git a/src/common/Display/dpi_aware.h b/src/common/Display/dpi_aware.h index a63365aa2fb7..bbbb61fd4046 100644 --- a/src/common/Display/dpi_aware.h +++ b/src/common/Display/dpi_aware.h @@ -15,6 +15,7 @@ namespace DPIAware void Convert(HMONITOR monitor_handle, RECT& rect); void ConvertByCursorPosition(float& width, float& height); void InverseConvert(HMONITOR monitor_handle, float& width, float& height); + void InverseConvert(HMONITOR monitor_handle, RECT& rect); void EnableDPIAwarenessForThisProcess(); enum AwarenessLevel diff --git a/src/modules/Workspaces/WorkspacesEditor/Data/ProjectData.cs b/src/modules/Workspaces/WorkspacesEditor/Data/ProjectData.cs index 4a0897fef8d0..050591591a04 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Data/ProjectData.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Data/ProjectData.cs @@ -3,9 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; - -using Workspaces.Data; - using static WorkspacesEditor.Data.ProjectData; namespace WorkspacesEditor.Data diff --git a/src/modules/Workspaces/WorkspacesEditor/Data/TempProjectData.cs b/src/modules/Workspaces/WorkspacesEditor/Data/TempProjectData.cs index b3de2f5b4df2..a1600885b983 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Data/TempProjectData.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Data/TempProjectData.cs @@ -8,13 +8,7 @@ namespace WorkspacesEditor.Data { public class TempProjectData : ProjectData { - public static string File - { - get - { - return FolderUtils.DataFolder() + "\\temp-workspaces.json"; - } - } + public static string File => FolderUtils.DataFolder() + "\\temp-workspaces.json"; public static void DeleteTempFile() { diff --git a/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesData.cs b/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesData.cs index a16ba2c3c6c7..6e0d015905fa 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesData.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesData.cs @@ -3,8 +3,6 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; - -using Workspaces.Data; using WorkspacesEditor.Utils; using static WorkspacesEditor.Data.ProjectData; @@ -14,13 +12,7 @@ namespace WorkspacesEditor.Data { public class WorkspacesData : WorkspacesEditorData { - public string File - { - get - { - return FolderUtils.DataFolder() + "\\workspaces.json"; - } - } + public string File => FolderUtils.DataFolder() + "\\workspaces.json"; public struct WorkspacesListWrapper { diff --git a/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesEditorData`1.cs b/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesEditorData`1.cs index e2492d839fa5..c2ad0a70a466 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesEditorData`1.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Data/WorkspacesEditorData`1.cs @@ -3,28 +3,24 @@ // See the LICENSE file in the project root for more information. using System.Text.Json; - using WorkspacesEditor.Utils; -namespace Workspaces.Data +namespace WorkspacesEditor.Data { public class WorkspacesEditorData { protected JsonSerializerOptions JsonOptions { - get + get => new() { - return new JsonSerializerOptions - { - PropertyNamingPolicy = new DashCaseNamingPolicy(), - WriteIndented = true, - }; - } + PropertyNamingPolicy = new DashCaseNamingPolicy(), + WriteIndented = true, + }; } public T Read(string file) { - IOUtils ioUtils = new IOUtils(); + IOUtils ioUtils = new(); string data = ioUtils.ReadFile(file); return JsonSerializer.Deserialize(data, JsonOptions); } diff --git a/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml b/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml index 0c5eb55ccc36..29630a910c98 100644 --- a/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml +++ b/src/modules/Workspaces/WorkspacesEditor/MainWindow.xaml @@ -8,7 +8,7 @@ xmlns:ui="http://schemas.modernwpf.com/2019" x:Name="WorkspacesMainWindow" Title="{x:Static props:Resources.MainTitle}" - MinWidth="700" + MinWidth="750" MinHeight="680" ui:TitleBar.Background="{DynamicResource PrimaryBackgroundBrush}" ui:TitleBar.InactiveBackground="{DynamicResource TertiaryBackgroundBrush}" diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/AppListDataTemplateSelector.cs b/src/modules/Workspaces/WorkspacesEditor/Models/AppListDataTemplateSelector.cs index 660793c1c23f..78a88595f1ec 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Models/AppListDataTemplateSelector.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Models/AppListDataTemplateSelector.cs @@ -18,14 +18,7 @@ public AppListDataTemplateSelector() public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) { - if (item is MonitorHeaderRow) - { - return HeaderTemplate; - } - else - { - return AppTemplate; - } + return item is MonitorHeaderRow ? HeaderTemplate : AppTemplate; } } } diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs b/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs index 3d30c38cab51..7d8bed64dea8 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Models/Application.cs @@ -1,25 +1,22 @@ -// Copyright (c) Microsoft Corporation +// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.ComponentModel; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; using System.Globalization; -using System.IO; -using System.Linq; using System.Text.Json.Serialization; -using System.Text.RegularExpressions; -using System.Windows.Media.Imaging; -using ManagedCommon; -using Windows.Management.Deployment; -using WorkspacesCsharpLibrary; using WorkspacesCsharpLibrary.Models; namespace WorkspacesEditor.Models { + public enum WindowPositionKind + { + Custom = 0, + Maximized = 1, + Minimized = 2, + } + public class Application : BaseApplication, IDisposable { private bool _isInitialized; @@ -79,7 +76,7 @@ public struct WindowPosition return left.X != right.X || left.Y != right.Y || left.Width != right.Width || left.Height != right.Height; } - public override bool Equals(object obj) + public override readonly bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { @@ -90,7 +87,7 @@ public override bool Equals(object obj) return X == pos.X && Y == pos.Y && Width == pos.Width && Height == pos.Height; } - public override int GetHashCode() + public override readonly int GetHashCode() { return base.GetHashCode(); } @@ -136,36 +133,24 @@ private void RedrawPreviewImage() } } - private bool _minimized; + public bool Minimized { get; set; } - public bool Minimized - { - get => _minimized; - set - { - _minimized = value; - OnPropertyChanged(new PropertyChangedEventArgs(nameof(Minimized))); - OnPropertyChanged(new PropertyChangedEventArgs(nameof(EditPositionEnabled))); - RedrawPreviewImage(); - } - } + public bool Maximized { get; set; } - private bool _maximized; + public bool EditPositionEnabled => !Minimized && !Maximized; - public bool Maximized + public int PositionComboboxIndex { - get => _maximized; + get => Maximized ? (int)WindowPositionKind.Maximized : Minimized ? (int)WindowPositionKind.Minimized : (int)WindowPositionKind.Custom; set { - _maximized = value; - OnPropertyChanged(new PropertyChangedEventArgs(nameof(Maximized))); + Maximized = value == (int)WindowPositionKind.Maximized; + Minimized = value == (int)WindowPositionKind.Minimized; OnPropertyChanged(new PropertyChangedEventArgs(nameof(EditPositionEnabled))); RedrawPreviewImage(); } } - public bool EditPositionEnabled { get => !Minimized && !Maximized; } - private string _appMainParams; public string AppMainParams @@ -183,7 +168,7 @@ public string AppMainParams } } - public bool IsAppMainParamVisible { get => !string.IsNullOrWhiteSpace(_appMainParams); } + public bool IsAppMainParamVisible => !string.IsNullOrWhiteSpace(_appMainParams); [JsonIgnore] public bool IsHighlighted { get; set; } @@ -192,13 +177,7 @@ public string AppMainParams public int RepeatIndex { get; set; } [JsonIgnore] - public string RepeatIndexString - { - get - { - return RepeatIndex <= 1 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture); - } - } + public string RepeatIndexString => RepeatIndex <= 1 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture); private WindowPosition _position; @@ -242,10 +221,7 @@ public MonitorSetup MonitorSetup { get { - if (_monitorSetup == null) - { - _monitorSetup = Parent.GetMonitorForApp(this); - } + _monitorSetup ??= Parent.GetMonitorForApp(this); return _monitorSetup; } @@ -271,7 +247,7 @@ public bool IsExpanded } } - public string DeleteButtonContent { get => _isIncluded ? Properties.Resources.Delete : Properties.Resources.AddBack; } + public string DeleteButtonContent => _isIncluded ? Properties.Resources.Delete : Properties.Resources.AddBack; private bool _isIncluded = true; @@ -298,15 +274,5 @@ internal void CommandLineTextChanged(string newCommandLineValue) CommandLineArguments = newCommandLineValue; OnPropertyChanged(new PropertyChangedEventArgs(nameof(AppMainParams))); } - - internal void MaximizedChecked() - { - Minimized = false; - } - - internal void MinimizedChecked() - { - Maximized = false; - } } } diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/Monitor.cs b/src/modules/Workspaces/WorkspacesEditor/Models/Monitor.cs index 2a911eb1fe65..368223c6e484 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Models/Monitor.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Models/Monitor.cs @@ -6,28 +6,18 @@ namespace WorkspacesEditor.Models { - public class Monitor + public class Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds) { - public string MonitorName { get; private set; } + public string MonitorName { get; private set; } = monitorName; - public string MonitorInstanceId { get; private set; } + public string MonitorInstanceId { get; private set; } = monitorInstanceId; - public int MonitorNumber { get; private set; } + public int MonitorNumber { get; private set; } = number; - public int Dpi { get; private set; } + public int Dpi { get; private set; } = dpi; - public Rect MonitorDpiUnawareBounds { get; private set; } + public Rect MonitorDpiUnawareBounds { get; private set; } = dpiUnawareBounds; - public Rect MonitorDpiAwareBounds { get; private set; } - - public Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds) - { - MonitorName = monitorName; - MonitorInstanceId = monitorInstanceId; - MonitorNumber = number; - Dpi = dpi; - MonitorDpiAwareBounds = dpiAwareBounds; - MonitorDpiUnawareBounds = dpiUnawareBounds; - } + public Rect MonitorDpiAwareBounds { get; private set; } = dpiAwareBounds; } } diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/MonitorSetup.cs b/src/modules/Workspaces/WorkspacesEditor/Models/MonitorSetup.cs index e44365a98803..a51ede204717 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Models/MonitorSetup.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Models/MonitorSetup.cs @@ -16,9 +16,9 @@ public void OnPropertyChanged(PropertyChangedEventArgs e) PropertyChanged?.Invoke(this, e); } - public string MonitorInfo { get => MonitorName; } + public string MonitorInfo => MonitorName; - public string MonitorInfoWithResolution { get => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}"; } + public string MonitorInfoWithResolution => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}"; public MonitorSetup(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds) : base(monitorName, monitorInstanceId, number, dpi, dpiAwareBounds, dpiUnawareBounds) diff --git a/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs b/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs index 19b867f38889..0c44440d394e 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Models/Project.cs @@ -29,10 +29,7 @@ public class Project : INotifyPropertyChanged public string Name { - get - { - return _name; - } + get => _name; set { @@ -68,8 +65,7 @@ public string LastLaunched DateTime lastLaunchDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(LastLaunchedTime); - var now = DateTime.UtcNow.Ticks; - var ts = DateTime.UtcNow - lastLaunchDateTime; + TimeSpan ts = DateTime.UtcNow - lastLaunchDateTime; double delta = Math.Abs(ts.TotalSeconds); if (delta < 1 * MINUTE) @@ -120,10 +116,7 @@ public string LastLaunched } } - public bool CanBeSaved - { - get => Name.Length > 0 && Applications.Count > 0; - } + public bool CanBeSaved => Name.Length > 0 && Applications.Count > 0; private bool _isRevertEnabled; @@ -145,10 +138,7 @@ public bool IsRevertEnabled [JsonIgnore] public bool IsPopupVisible { - get - { - return _isPopupVisible; - } + get => _isPopupVisible; set { @@ -163,11 +153,11 @@ public List ApplicationsListed { get { - List applicationsListed = new List(); + List applicationsListed = []; ILookup apps = Applications.Where(x => !x.Minimized).ToLookup(x => x.MonitorSetup); - foreach (var appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top)) + foreach (IGrouping appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top)) { - MonitorHeaderRow headerRow = new MonitorHeaderRow { MonitorName = "Screen " + appItem.Key.MonitorNumber, SelectString = Properties.Resources.SelectAllAppsOnMonitor + " " + appItem.Key.MonitorInfo }; + MonitorHeaderRow headerRow = new() { MonitorName = "Screen " + appItem.Key.MonitorNumber, SelectString = Properties.Resources.SelectAllAppsOnMonitor + " " + appItem.Key.MonitorInfo }; applicationsListed.Add(headerRow); foreach (Application app in appItem) { @@ -175,10 +165,10 @@ public List ApplicationsListed } } - var minimizedApps = Applications.Where(x => x.Minimized); + IEnumerable minimizedApps = Applications.Where(x => x.Minimized); if (minimizedApps.Any()) { - MonitorHeaderRow headerRow = new MonitorHeaderRow { MonitorName = Properties.Resources.Minimized_Apps, SelectString = Properties.Resources.SelectAllMinimizedApps }; + MonitorHeaderRow headerRow = new() { MonitorName = Properties.Resources.Minimized_Apps, SelectString = Properties.Resources.SelectAllMinimizedApps }; applicationsListed.Add(headerRow); foreach (Application app in minimizedApps) { @@ -219,17 +209,17 @@ public Project(Project selectedProject) int screenIndex = 1; - Monitors = new List(); - foreach (var item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top)) + Monitors = []; + foreach (MonitorSetup item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top)) { Monitors.Add(item); screenIndex++; } - Applications = new List(); - foreach (var item in selectedProject.Applications) + Applications = []; + foreach (Application item in selectedProject.Applications) { - Application newApp = new Application(item); + Application newApp = new(item); newApp.Parent = this; newApp.InitializationFinished(); Applications.Add(newApp); @@ -244,14 +234,14 @@ public Project(ProjectData.ProjectWrapper project) LastLaunchedTime = project.LastLaunchedTime; IsShortcutNeeded = project.IsShortcutNeeded; MoveExistingWindows = project.MoveExistingWindows; - Monitors = new List() { }; - Applications = new List { }; + Monitors = []; + Applications = []; - foreach (var app in project.Applications) + foreach (ProjectData.ApplicationWrapper app in project.Applications) { - Models.Application newApp = new Models.Application() + Models.Application newApp = new() { - Id = string.IsNullOrEmpty(app.Id) ? $"{{{Guid.NewGuid().ToString()}}}" : app.Id, + Id = string.IsNullOrEmpty(app.Id) ? $"{{{Guid.NewGuid()}}}" : app.Id, AppName = app.Application, AppPath = app.ApplicationPath, AppTitle = app.Title, @@ -278,20 +268,17 @@ public Project(ProjectData.ProjectWrapper project) Applications.Add(newApp); } - foreach (var monitor in project.MonitorConfiguration) + foreach (ProjectData.MonitorConfigurationWrapper monitor in project.MonitorConfiguration) { - System.Windows.Rect dpiAware = new System.Windows.Rect(monitor.MonitorRectDpiAware.Left, monitor.MonitorRectDpiAware.Top, monitor.MonitorRectDpiAware.Width, monitor.MonitorRectDpiAware.Height); - System.Windows.Rect dpiUnaware = new System.Windows.Rect(monitor.MonitorRectDpiUnaware.Left, monitor.MonitorRectDpiUnaware.Top, monitor.MonitorRectDpiUnaware.Width, monitor.MonitorRectDpiUnaware.Height); + System.Windows.Rect dpiAware = new(monitor.MonitorRectDpiAware.Left, monitor.MonitorRectDpiAware.Top, monitor.MonitorRectDpiAware.Width, monitor.MonitorRectDpiAware.Height); + System.Windows.Rect dpiUnaware = new(monitor.MonitorRectDpiUnaware.Left, monitor.MonitorRectDpiUnaware.Top, monitor.MonitorRectDpiUnaware.Width, monitor.MonitorRectDpiUnaware.Height); Monitors.Add(new MonitorSetup(monitor.Id, monitor.InstanceId, monitor.MonitorNumber, monitor.Dpi, dpiAware, dpiUnaware)); } } public BitmapImage PreviewIcons { - get - { - return _previewIcons; - } + get => _previewIcons; set { @@ -302,10 +289,7 @@ public BitmapImage PreviewIcons public BitmapImage PreviewImage { - get - { - return _previewImage; - } + get => _previewImage; set { @@ -316,10 +300,7 @@ public BitmapImage PreviewImage public double PreviewImageWidth { - get - { - return _previewImageWidth; - } + get => _previewImageWidth; set { @@ -366,6 +347,7 @@ public void UpdateAfterLaunchAndEdit(Project other) Id = other.Id; Name = other.Name; IsRevertEnabled = true; + MoveExistingWindows = other.MoveExistingWindows; } internal void CloseExpanders() @@ -378,13 +360,13 @@ internal void CloseExpanders() internal MonitorSetup GetMonitorForApp(Application app) { - var monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault(); + MonitorSetup monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault(); if (monitorSetup == null) { // monitors changed: try to determine monitor id based on middle point int middleX = app.Position.X + (app.Position.Width / 2); int middleY = app.Position.Y + (app.Position.Height / 2); - var monitorCandidate = Monitors.Where(x => + MonitorSetup monitorCandidate = Monitors.Where(x => (x.MonitorDpiUnawareBounds.Left < middleX) && (x.MonitorDpiUnawareBounds.Right > middleX) && (x.MonitorDpiUnawareBounds.Top < middleY) && diff --git a/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.Designer.cs b/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.Designer.cs index ce81b9785d04..f444c1dd2f6e 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.Designer.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.Designer.cs @@ -61,7 +61,7 @@ internal Resources() { } /// - /// Looks up a localized string similar to Add Back. + /// Looks up a localized string similar to Add back. /// public static string AddBack { get { @@ -78,15 +78,6 @@ public static string Admin { } } - /// - /// Looks up a localized string similar to Launch new app instances. - /// - public static string AlwaysLaunch { - get { - return ResourceManager.GetString("AlwaysLaunch", resourceCulture); - } - } - /// /// Looks up a localized string similar to app. /// @@ -169,7 +160,7 @@ public static string Created { } /// - /// Looks up a localized string similar to Create Desktop Shortcut. + /// Looks up a localized string similar to Create desktop shortcut. /// public static string CreateShortcut { get { @@ -186,6 +177,15 @@ public static string CreateWorkspace { } } + /// + /// Looks up a localized string similar to Custom. + /// + public static string Custom { + get { + return ResourceManager.GetString("Custom", resourceCulture); + } + } + /// /// Looks up a localized string similar to days ago. /// @@ -223,7 +223,7 @@ public static string Delete_Workspace_Dialog_Announce { } /// - /// Looks up a localized string similar to Remove Selected Apps. + /// Looks up a localized string similar to Remove selected apps. /// public static string DeleteSelected { get { @@ -322,7 +322,7 @@ public static string LaunchAsAdmin { } /// - /// Looks up a localized string similar to Launch & Edit. + /// Looks up a localized string similar to Launch & edit. /// public static string LaunchEdit { get { @@ -367,7 +367,7 @@ public static string Minimized { } /// - /// Looks up a localized string similar to Minimized Apps. + /// Looks up a localized string similar to Minimized apps. /// public static string Minimized_Apps { get { @@ -394,7 +394,7 @@ public static string MonthsAgo { } /// - /// Looks up a localized string similar to Move apps if present. + /// Looks up a localized string similar to Move existing windows. /// public static string MoveIfExist { get { @@ -502,7 +502,7 @@ public static string OneYearAgo { } /// - /// Looks up a localized string similar to Pin Workspaces to Taskbar. + /// Looks up a localized string similar to Pin Workspaces to taskbar. /// public static string PinToTaskbar { get { @@ -565,7 +565,7 @@ public static string SecondsAgo { } /// - /// Looks up a localized string similar to Select All Apps on. + /// Looks up a localized string similar to Select all apps on. /// public static string SelectAllAppsOnMonitor { get { @@ -574,7 +574,7 @@ public static string SelectAllAppsOnMonitor { } /// - /// Looks up a localized string similar to Select All Minimized Apps. + /// Looks up a localized string similar to Select all minimized apps. /// public static string SelectAllMinimizedApps { get { @@ -583,7 +583,7 @@ public static string SelectAllMinimizedApps { } /// - /// Looks up a localized string similar to Select All Apps in Workspace. + /// Looks up a localized string similar to Select all apps in Workspace. /// public static string SelectedAllInWorkspace { get { @@ -645,6 +645,15 @@ public static string Width { } } + /// + /// Looks up a localized string similar to Window position. + /// + public static string WindowPosition { + get { + return ResourceManager.GetString("WindowPosition", resourceCulture); + } + } + /// /// Looks up a localized string similar to Workspace name. /// diff --git a/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.resx b/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.resx index b768d6682a50..fc7079e9b641 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.resx +++ b/src/modules/Workspaces/WorkspacesEditor/Properties/Resources.resx @@ -123,9 +123,6 @@ Admin - - Launch new app instances - app @@ -160,6 +157,9 @@ Create desktop shortcut + + Custom + days ago @@ -231,7 +231,7 @@ months ago - Move apps if present + Move existing windows Name @@ -321,6 +321,9 @@ Width + + Window position + Write arguments here diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs index da215a5f0d5c..e70324567d7c 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/DrawHelper.cs @@ -20,21 +20,21 @@ namespace WorkspacesEditor.Utils { public class DrawHelper { - private static Font font = new("Tahoma", 24); - private static double scale = 0.1; + private static readonly Font Font = new("Tahoma", 24); + private static readonly double Scale = 0.1; private static double gapWidth; private static double gapHeight; public static BitmapImage DrawPreview(Project project, Rectangle bounds, Theme currentTheme) { - List horizontalGaps = new List(); - List verticalGaps = new List(); + List horizontalGaps = []; + List verticalGaps = []; gapWidth = bounds.Width * 0.01; gapHeight = bounds.Height * 0.01; int Scaled(double value) { - return (int)(value * scale); + return (int)(value * Scale); } int TransformX(double posX) @@ -54,7 +54,7 @@ Rectangle GetAppRect(Application app) if (app.Maximized) { Project project = app.Parent; - var monitor = project.GetMonitorForApp(app); + MonitorSetup monitor = project.GetMonitorForApp(app); if (monitor == null) { // unrealistic case, there are no monitors at all in the workspace, use original rect @@ -69,22 +69,23 @@ Rectangle GetAppRect(Application app) } } - Dictionary repeatCounter = new Dictionary(); + Dictionary repeatCounter = []; - var appsIncluded = project.Applications.Where(x => x.IsIncluded); + IEnumerable appsIncluded = project.Applications.Where(x => x.IsIncluded); foreach (Application app in appsIncluded) { - if (repeatCounter.TryGetValue(app.AppPath + app.AppTitle, out int value)) + string appIdentifier = app.AppPath + app.PwaAppId; + if (repeatCounter.TryGetValue(appIdentifier, out int value)) { - repeatCounter[app.AppPath + app.AppTitle] = ++value; + repeatCounter[appIdentifier] = ++value; } else { - repeatCounter.Add(app.AppPath + app.AppTitle, 1); + repeatCounter.Add(appIdentifier, 1); } - app.RepeatIndex = repeatCounter[app.AppPath + app.AppTitle]; + app.RepeatIndex = repeatCounter[appIdentifier]; } foreach (Application app in project.Applications.Where(x => !x.IsIncluded)) @@ -113,7 +114,7 @@ Rectangle GetAppRect(Application app) } } - Bitmap previewBitmap = new Bitmap(Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled((bounds.Height * 1.2) + (horizontalGaps.Count * gapHeight))); + Bitmap previewBitmap = new(Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled((bounds.Height * 1.2) + (horizontalGaps.Count * gapHeight))); double desiredIconSize = Scaled(Math.Min(bounds.Width, bounds.Height)) * 0.25; using (Graphics g = Graphics.FromImage(previewBitmap)) { @@ -131,7 +132,7 @@ Rectangle GetAppRect(Application app) g.FillRectangle(monitorBrush, new Rectangle(TransformX(monitor.MonitorDpiAwareBounds.Left), TransformY(monitor.MonitorDpiAwareBounds.Top), Scaled(monitor.MonitorDpiAwareBounds.Width), Scaled(monitor.MonitorDpiAwareBounds.Height))); } - var appsToDraw = appsIncluded.Where(x => !x.Minimized); + IEnumerable appsToDraw = appsIncluded.Where(x => !x.Minimized); // draw the highlighted app at the end to have its icon in the foreground for the case there are overlapping icons foreach (Application app in appsToDraw.Where(x => !x.IsHighlighted)) @@ -147,24 +148,22 @@ Rectangle GetAppRect(Application app) } // draw the minimized windows - Rectangle rectMinimized = new Rectangle(0, Scaled((bounds.Height * 1.02) + (horizontalGaps.Count * gapHeight)), Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled(bounds.Height * 0.18)); + Rectangle rectMinimized = new(0, Scaled((bounds.Height * 1.02) + (horizontalGaps.Count * gapHeight)), Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled(bounds.Height * 0.18)); DrawWindow(g, brush, brushForHighlight, rectMinimized, appsIncluded.Where(x => x.Minimized), currentTheme); } - using (var memory = new MemoryStream()) - { - previewBitmap.Save(memory, ImageFormat.Png); - memory.Position = 0; + using MemoryStream memory = new(); + previewBitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; - var bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.StreamSource = memory; - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.EndInit(); - bitmapImage.Freeze(); + BitmapImage bitmapImage = new(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + bitmapImage.Freeze(); - return bitmapImage; - } + return bitmapImage; } public static void DrawWindow(Graphics graphics, Brush brush, Rectangle bounds, Application app, double desiredIconSize, Theme currentTheme) @@ -194,7 +193,7 @@ public static void DrawWindow(Graphics graphics, Brush brush, Rectangle bounds, } double iconSize = Math.Min(Math.Min(bounds.Width - 4, bounds.Height - 4), desiredIconSize); - Rectangle iconBounds = new Rectangle((int)(bounds.Left + (bounds.Width / 2) - (iconSize / 2)), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize); + Rectangle iconBounds = new((int)(bounds.Left + (bounds.Width / 2) - (iconSize / 2)), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize); try { @@ -203,13 +202,13 @@ public static void DrawWindow(Graphics graphics, Brush brush, Rectangle bounds, { string indexString = app.RepeatIndex.ToString(CultureInfo.InvariantCulture); int indexSize = (int)(iconBounds.Width * 0.5); - Rectangle indexBounds = new Rectangle(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize); + Rectangle indexBounds = new(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize); - var textSize = graphics.MeasureString(indexString, font); - var state = graphics.Save(); + SizeF textSize = graphics.MeasureString(indexString, Font); + GraphicsState state = graphics.Save(); graphics.TranslateTransform(indexBounds.Left, indexBounds.Top); graphics.ScaleTransform(indexBounds.Width / textSize.Width, indexBounds.Height / textSize.Height); - graphics.DrawString(indexString, font, Brushes.Black, PointF.Empty); + graphics.DrawString(indexString, Font, Brushes.Black, PointF.Empty); graphics.Restore(state); } } @@ -255,7 +254,7 @@ public static void DrawWindow(Graphics graphics, Brush brush, Brush brushForHigh for (int iconCounter = 0; iconCounter < appsCount; iconCounter++) { Application app = apps.ElementAt(iconCounter); - Rectangle iconBounds = new Rectangle((int)(bounds.Left + (bounds.Width / 2) - (iconSize * ((appsCount / 2) - iconCounter))), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize); + Rectangle iconBounds = new((int)(bounds.Left + (bounds.Width / 2) - (iconSize * ((appsCount / 2) - iconCounter))), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize); try { @@ -264,13 +263,13 @@ public static void DrawWindow(Graphics graphics, Brush brush, Brush brushForHigh { string indexString = app.RepeatIndex.ToString(CultureInfo.InvariantCulture); int indexSize = (int)(iconBounds.Width * 0.5); - Rectangle indexBounds = new Rectangle(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize); + Rectangle indexBounds = new(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize); - var textSize = graphics.MeasureString(indexString, font); - var state = graphics.Save(); + SizeF textSize = graphics.MeasureString(indexString, Font); + GraphicsState state = graphics.Save(); graphics.TranslateTransform(indexBounds.Left, indexBounds.Top); graphics.ScaleTransform(indexBounds.Width / textSize.Width, indexBounds.Height / textSize.Height); - graphics.DrawString(indexString, font, Brushes.Black, PointF.Empty); + graphics.DrawString(indexString, Font, Brushes.Black, PointF.Empty); graphics.Restore(state); } } @@ -289,14 +288,14 @@ public static BitmapImage DrawPreviewIcons(Project project) return null; } - Bitmap previewBitmap = new Bitmap(32 * appsCount, 24); + Bitmap previewBitmap = new(32 * appsCount, 24); using (Graphics graphics = Graphics.FromImage(previewBitmap)) { graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; int appIndex = 0; - foreach (var app in project.Applications) + foreach (Application app in project.Applications) { try { @@ -311,20 +310,18 @@ public static BitmapImage DrawPreviewIcons(Project project) } } - using (var memory = new MemoryStream()) - { - previewBitmap.Save(memory, ImageFormat.Png); - memory.Position = 0; + using MemoryStream memory = new(); + previewBitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; - var bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.StreamSource = memory; - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.EndInit(); - bitmapImage.Freeze(); + BitmapImage bitmapImage = new(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + bitmapImage.Freeze(); - return bitmapImage; - } + return bitmapImage; } private static GraphicsPath RoundedRect(Rectangle bounds) @@ -333,9 +330,9 @@ private static GraphicsPath RoundedRect(Rectangle bounds) int radius = (int)(minorSize / 8); int diameter = radius * 2; - Size size = new Size(diameter, diameter); - Rectangle arc = new Rectangle(bounds.Location, size); - GraphicsPath path = new GraphicsPath(); + Size size = new(diameter, diameter); + Rectangle arc = new(bounds.Location, size); + GraphicsPath path = new(); if (radius == 0) { diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/IOUtils.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/IOUtils.cs index 075067cb142b..fe697775934d 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/IOUtils.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/IOUtils.cs @@ -26,18 +26,16 @@ public string ReadFile(string fileName) { if (_fileSystem.File.Exists(fileName)) { - var attempts = 0; + int attempts = 0; while (attempts < 10) { try { - using (FileSystemStream inputStream = _fileSystem.File.Open(fileName, FileMode.Open)) - using (StreamReader reader = new StreamReader(inputStream)) - { - string data = reader.ReadToEnd(); - inputStream.Close(); - return data; - } + using FileSystemStream inputStream = _fileSystem.File.Open(fileName, FileMode.Open); + using StreamReader reader = new(inputStream); + string data = reader.ReadToEnd(); + inputStream.Close(); + return data; } catch (Exception) { diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/MonitorHelper.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/MonitorHelper.cs index d2f2c0b0bf32..450afb5070ef 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/MonitorHelper.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/MonitorHelper.cs @@ -26,7 +26,7 @@ private void SaveDpiUnawareScreens() private Screen[] GetDpiUnawareScreenBounds() { - Thread dpiUnawareThread = new Thread(new ThreadStart(SaveDpiUnawareScreens)); + Thread dpiUnawareThread = new(new ThreadStart(SaveDpiUnawareScreens)); dpiUnawareThread.Start(); dpiUnawareThread.Join(); @@ -35,15 +35,15 @@ private Screen[] GetDpiUnawareScreenBounds() public static Screen[] GetDpiUnawareScreens() { - MonitorHelper monitorHelper = new MonitorHelper(); + MonitorHelper monitorHelper = new(); return monitorHelper.GetDpiUnawareScreenBounds(); } internal static double GetScreenDpiFromScreen(Screen screen) { - var point = new System.Drawing.Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1); - var monitor = NativeMethods.MonitorFromPoint(point, NativeMethods._MONITOR_DEFAULTTONEAREST); - NativeMethods.GetDpiForMonitor(monitor, NativeMethods.DpiType.EFFECTIVE, out uint dpiX, out uint dpiY); + System.Drawing.Point point = new(screen.Bounds.Left + 1, screen.Bounds.Top + 1); + nint monitor = NativeMethods.MonitorFromPoint(point, NativeMethods._MONITOR_DEFAULTTONEAREST); + _ = NativeMethods.GetDpiForMonitor(monitor, NativeMethods.DpiType.EFFECTIVE, out uint dpiX, out _); return dpiX / 96.0; } } diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/ParsingResult.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/ParsingResult.cs index 59389f27d612..57f3bbf0003c 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/ParsingResult.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/ParsingResult.cs @@ -4,19 +4,12 @@ namespace WorkspacesEditor.Utils { - public struct ParsingResult + public readonly struct ParsingResult(bool result, string message = "", string data = "") { - public bool Result { get; } + public bool Result { get; } = result; - public string Message { get; } + public string Message { get; } = message; - public string MalformedData { get; } - - public ParsingResult(bool result, string message = "", string data = "") - { - Result = result; - Message = message; - MalformedData = data; - } + public string MalformedData { get; } = data; } } diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs index 48cbafb0aac7..29dd65d56f77 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/Settings.cs @@ -9,13 +9,13 @@ namespace WorkspacesEditor.Utils public class Settings { private const string WorkspacesModuleName = "Workspaces"; - private static SettingsUtils _settingsUtils = new SettingsUtils(); + private static readonly SettingsUtils _settingsUtils = new(); public static WorkspacesSettings ReadSettings() { if (!_settingsUtils.SettingsExists(WorkspacesModuleName)) { - var defaultWorkspacesSettings = new WorkspacesSettings(); + WorkspacesSettings defaultWorkspacesSettings = new(); defaultWorkspacesSettings.Save(_settingsUtils); return defaultWorkspacesSettings; } diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/StringUtils.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/StringUtils.cs index c01b10252c05..3d2d146de2f1 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/StringUtils.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/StringUtils.cs @@ -11,12 +11,9 @@ public static class StringUtils public static string UpperCamelCaseToDashCase(this string str) { // If it's single letter variable, leave it as it is - if (str.Length == 1) - { - return str; - } - - return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant(); + return str.Length == 1 + ? str + : string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant(); } } } diff --git a/src/modules/Workspaces/WorkspacesEditor/Utils/WorkspacesEditorIO.cs b/src/modules/Workspaces/WorkspacesEditor/Utils/WorkspacesEditorIO.cs index 7ad416cf17db..c467259521f5 100644 --- a/src/modules/Workspaces/WorkspacesEditor/Utils/WorkspacesEditorIO.cs +++ b/src/modules/Workspaces/WorkspacesEditor/Utils/WorkspacesEditorIO.cs @@ -24,7 +24,7 @@ public ParsingResult ParseWorkspaces(MainViewModel mainViewModel) { try { - WorkspacesData parser = new WorkspacesData(); + WorkspacesData parser = new(); if (!File.Exists(parser.File)) { Logger.LogWarning($"Workspaces storage file not found: {parser.File}"); @@ -56,14 +56,14 @@ public Project ParseTempProject() { try { - ProjectData parser = new ProjectData(); + ProjectData parser = new(); if (!File.Exists(TempProjectData.File)) { Logger.LogWarning($"ParseProject method. Workspaces storage file not found: {TempProjectData.File}"); return null; } - Project project = new Project(parser.Read(TempProjectData.File)); + Project project = new(parser.Read(TempProjectData.File)); return project; } catch (Exception e) @@ -75,13 +75,13 @@ public Project ParseTempProject() public void SerializeWorkspaces(List workspaces, bool useTempFile = false) { - WorkspacesData serializer = new WorkspacesData(); - WorkspacesData.WorkspacesListWrapper workspacesWrapper = new WorkspacesData.WorkspacesListWrapper { }; - workspacesWrapper.Workspaces = new List(); + WorkspacesData serializer = new(); + WorkspacesData.WorkspacesListWrapper workspacesWrapper = new() { }; + workspacesWrapper.Workspaces = []; foreach (Project project in workspaces) { - ProjectData.ProjectWrapper wrapper = new ProjectData.ProjectWrapper + ProjectData.ProjectWrapper wrapper = new() { Id = project.Id, Name = project.Name, @@ -89,11 +89,11 @@ public void SerializeWorkspaces(List workspaces, bool useTempFile = fal IsShortcutNeeded = project.IsShortcutNeeded, MoveExistingWindows = project.MoveExistingWindows, LastLaunchedTime = project.LastLaunchedTime, - Applications = new List { }, - MonitorConfiguration = new List { }, + Applications = [], + MonitorConfiguration = [], }; - foreach (var app in project.Applications.Where(x => x.IsIncluded)) + foreach (Application app in project.Applications.Where(x => x.IsIncluded)) { wrapper.Applications.Add(new ProjectData.ApplicationWrapper { @@ -120,7 +120,7 @@ public void SerializeWorkspaces(List workspaces, bool useTempFile = fal }); } - foreach (var monitor in project.Monitors) + foreach (MonitorSetup monitor in project.Monitors) { wrapper.MonitorConfiguration.Add(new ProjectData.MonitorConfigurationWrapper { @@ -150,7 +150,7 @@ public void SerializeWorkspaces(List workspaces, bool useTempFile = fal try { - IOUtils ioUtils = new IOUtils(); + IOUtils ioUtils = new(); ioUtils.WriteFile(useTempFile ? TempProjectData.File : serializer.File, serializer.Serialize(workspacesWrapper)); } catch (Exception e) @@ -162,7 +162,7 @@ public void SerializeWorkspaces(List workspaces, bool useTempFile = fal private bool AddWorkspaces(MainViewModel mainViewModel, WorkspacesData.WorkspacesListWrapper workspaces) { - foreach (var project in workspaces.Workspaces) + foreach (ProjectData.ProjectWrapper project in workspaces.Workspaces) { mainViewModel.Workspaces.Add(new Project(project)); } @@ -173,13 +173,13 @@ private bool AddWorkspaces(MainViewModel mainViewModel, WorkspacesData.Workspace private bool SetWorkspaces(MainViewModel mainViewModel, WorkspacesData.WorkspacesListWrapper workspaces) { - mainViewModel.Workspaces = new System.Collections.ObjectModel.ObservableCollection { }; + mainViewModel.Workspaces = []; return AddWorkspaces(mainViewModel, workspaces); } internal void SerializeTempProject(Project project) { - SerializeWorkspaces(new List() { project }, true); + SerializeWorkspaces([project], true); } } } diff --git a/src/modules/Workspaces/WorkspacesEditor/WorkspacesEditorPage.xaml b/src/modules/Workspaces/WorkspacesEditor/WorkspacesEditorPage.xaml index e176ff432b66..6bc7bfe63798 100644 --- a/src/modules/Workspaces/WorkspacesEditor/WorkspacesEditorPage.xaml +++ b/src/modules/Workspaces/WorkspacesEditor/WorkspacesEditorPage.xaml @@ -156,24 +156,33 @@ Content="{x:Static props:Resources.LaunchAsAdmin}" IsChecked="{Binding IsElevated, Mode=TwoWay}" IsEnabled="{Binding CanLaunchElevated, Mode=OneWay}" /> - - + + + + + + - - diff --git a/src/modules/launcher/PowerLauncher/SettingsReader.cs b/src/modules/launcher/PowerLauncher/SettingsReader.cs index 835ef2bcd4db..d70d34a14455 100644 --- a/src/modules/launcher/PowerLauncher/SettingsReader.cs +++ b/src/modules/launcher/PowerLauncher/SettingsReader.cs @@ -159,7 +159,7 @@ public void ReadSettings() if (_settings.Theme != overloadSettings.Properties.Theme) { _settings.Theme = overloadSettings.Properties.Theme; - _themeManager.SetTheme(true); + _themeManager.UpdateTheme(); } if (_settings.StartupPosition != overloadSettings.Properties.Position) diff --git a/src/modules/launcher/PowerLauncher/Styles/FluentHC.xaml b/src/modules/launcher/PowerLauncher/Styles/FluentHC.xaml new file mode 100644 index 000000000000..91fc2b6d1fa5 --- /dev/null +++ b/src/modules/launcher/PowerLauncher/Styles/FluentHC.xaml @@ -0,0 +1,6710 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 11,5,11,6 + 1 + 8,0,0,0 + 14 + 22 + 22 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + 20 + + 1 + 8,6,0,0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12 + 14 + 20 + 28 + 40 + 68 + + + + + + + + 1,1,1,1 + 0,0,0,1 + 10,0,0,0 + 0,0,10,0 + 0,0,4,0 + 0,0,0,0 + 24 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9,6,9,8 + 320 + 1 + + + + + + + + + + + + + + + 12 + + 12 - - - - @@ -196,10 +216,10 @@ x:Name="PasteOptionsListView" Grid.Row="0" VerticalAlignment="Bottom" - IsItemClickEnabled="False" - ItemContainerStyle="{StaticResource PasteFormatListViewItemStyle}" + IsItemClickEnabled="True" + ItemClick="PasteFormat_ItemClick" ItemContainerTransitions="{x:Null}" - ItemTemplate="{StaticResource PasteFormatTemplate}" + ItemTemplateSelector="{StaticResource PasteFormatTemplateSelector}" ItemsSource="{x:Bind ViewModel.StandardPasteFormats, Mode=OneWay}" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollMode="Auto" @@ -217,10 +237,10 @@ x:Name="CustomActionsListView" Grid.Row="2" VerticalAlignment="Top" - IsItemClickEnabled="False" - ItemContainerStyle="{StaticResource PasteFormatListViewItemStyle}" + IsItemClickEnabled="True" + ItemClick="PasteFormat_ItemClick" ItemContainerTransitions="{x:Null}" - ItemTemplate="{StaticResource PasteFormatTemplate}" + ItemTemplateSelector="{StaticResource PasteFormatTemplateSelector}" ItemsSource="{x:Bind ViewModel.CustomActionPasteFormats, Mode=OneWay}" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollMode="Auto" @@ -232,7 +252,6 @@ Height="1" HorizontalAlignment="Stretch" Fill="{ThemeResource DividerStrokeColorDefaultBrush}" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9,6,9,8 - 320 - 1 - - - - - - - - - - - - - - + 16 + + + + IsReadOnly="True"> + + + + + + + + + + + + + + + + diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs index 1687a24293d3..06e435c9f0e4 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs @@ -8,6 +8,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.Windows.ApplicationModel.Resources; +using Windows.ApplicationModel.DataTransfer; namespace RegistryPreviewUILib { diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs index 3e0d16c9328f..1bf403c3fab1 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs @@ -3,6 +3,10 @@ // See the LICENSE file in the project root for more information. using System; +using System.Windows.Input; +using CommunityToolkit.Mvvm.Input; +using Microsoft.UI.Xaml; +using Windows.ApplicationModel.DataTransfer; namespace RegistryPreviewUILib { @@ -17,12 +21,16 @@ public class RegistryValue private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreview/deleted-value32.png"); private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreview/error32.png"); + public string Key { get; set; } + public string Name { get; set; } public string Type { get; set; } public string Value { get; set; } + public string ValueOneLine => Value.Replace('\r', ' '); + public string ToolTipText { get; set; } public Uri ImageUri @@ -46,12 +54,49 @@ public Uri ImageUri } } - public RegistryValue(string name, string type, string value) + public RegistryValue(string name, string type, string value, string key) { this.Name = name; this.Type = type; this.Value = value; this.ToolTipText = string.Empty; + this.Key = key; + } + + // Commands + public ICommand CopyToClipboardEntry_Click => new RelayCommand(CopyToClipboardEntry); + + public ICommand CopyToClipboardWithPath_Click => new RelayCommand(CopyToClipboardEntryWithPath); + + public ICommand CopyToClipboardName_Click => new RelayCommand(CopyToClipboardName); + + public ICommand CopyToClipboardType_Click => new RelayCommand(CopyToClipboardType); + + public ICommand CopyToClipboardData_Click => new RelayCommand(CopyToClipboardData); + + private void CopyToClipboardEntry() + { + ClipboardHelper.CopyToClipboardAction($"{Name}\r\n{Type}\r\n{Value}"); + } + + private void CopyToClipboardEntryWithPath() + { + ClipboardHelper.CopyToClipboardAction($"{Key}\r\n{Name}\r\n{Type}\r\n{Value}"); + } + + private void CopyToClipboardName() + { + ClipboardHelper.CopyToClipboardAction(Name); + } + + private void CopyToClipboardType() + { + ClipboardHelper.CopyToClipboardAction(Type); + } + + private void CopyToClipboardData() + { + ClipboardHelper.CopyToClipboardAction(Value); } } } diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw index 580d108d9a7b..9401908d216e 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw +++ b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw @@ -257,4 +257,28 @@ (zero-length binary value) + + Copy path + Like "Copy item" + + + Copy name + Like "Copy item" + + + Copy type + Like "Copy item" + + + Copy data + Like "Copy item" + + + Copy value + Like "Copy item" + + + Copy value with key path + Like "Copy item" + \ No newline at end of file From 1aaf764c14e171582faedccd2150872e36bf9342 Mon Sep 17 00:00:00 2001 From: Michael Clayton Date: Fri, 17 Jan 2025 15:41:39 +0000 Subject: [PATCH 081/103] [MWB] - refactoring "Common" classes - Common.Log.cs, Common.Receiver.cs (#35726) --- .../App/Class/Common.Clipboard.cs | 17 +- .../App/Class/Common.DragDrop.cs | 4 +- .../App/Class/Common.Event.cs | 4 +- .../App/Class/Common.InitAndCleanup.cs | 2 + .../App/Class/Common.Log.cs | 119 ----- .../App/Class/Common.MachineStuff.cs | 10 +- .../App/Class/Common.Receiver.cs | 431 ------------------ .../App/Class/Common.WinAPI.cs | 2 + .../MouseWithoutBorders/App/Class/Common.cs | 12 +- .../App/Class/IClipboardHelper.cs | 3 + .../MouseWithoutBorders/App/Class/Program.cs | 1 + .../MouseWithoutBorders/App/Class/Setting.cs | 3 +- .../App/Class/SocketStuff.cs | 4 +- .../App/Class/TcpServer.cs | 2 + .../MouseWithoutBorders/App/Core/Logger.cs | 12 +- .../MouseWithoutBorders/App/Core/Receiver.cs | 429 +++++++++++++++++ .../MouseWithoutBorders/App/Core/Thread.cs | 105 +++++ .../Core/Logger.PrivateDump.expected.txt | 188 ++++---- .../Core/LoggerTests.cs | 11 +- 19 files changed, 698 insertions(+), 661 deletions(-) delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.Log.cs delete mode 100644 src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/Receiver.cs create mode 100644 src/modules/MouseWithoutBorders/App/Core/Thread.cs diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs index 91fdfad11b5c..7654b0452d04 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs @@ -32,12 +32,17 @@ using MouseWithoutBorders.Exceptions; using SystemClipboard = System.Windows.Forms.Clipboard; +using Thread = MouseWithoutBorders.Core.Thread; namespace MouseWithoutBorders { internal partial class Common { - private const uint BIG_CLIPBOARD_DATA_TIMEOUT = 30000; + internal static readonly char[] Comma = new char[] { ',' }; + internal static readonly char[] Star = new char[] { '*' }; + internal static readonly char[] NullSeparator = new char[] { '\0' }; + + internal const uint BIG_CLIPBOARD_DATA_TIMEOUT = 30000; private const uint MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1024 * 1024; // 1MB private const uint MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 100 * 1024 * 1024; // 100MB private const int TEXT_HEADER_SIZE = 12; @@ -46,11 +51,9 @@ internal partial class Common private static long lastClipboardEventTime; private static string lastMachineWithClipboardData; private static string lastDragDropFile; - private static long clipboardCopiedTime; - - internal static readonly char[] Comma = new char[] { ',' }; - internal static readonly char[] Star = new char[] { '*' }; - internal static readonly char[] NullSeparator = new char[] { '\0' }; +#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter + internal static long clipboardCopiedTime; +#pragma warning restore SA1307 internal static ID LastIDWithClipboardData { get; set; } @@ -332,7 +335,7 @@ internal static void ReceiveClipboardDataUsingTCP(DATA data, bool image, TcpSk t break; default: - ProcessPackage(data, tcp); + Receiver.ProcessPackage(data, tcp); if (++unexpectedCount > 100) { Logger.Log("ReceiveClipboardDataUsingTCP: unexpectedCount > 100!"); diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs b/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs index f3ef0f139539..5426f93db062 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs @@ -22,6 +22,8 @@ using MouseWithoutBorders.Class; using MouseWithoutBorders.Core; +using Thread = MouseWithoutBorders.Core.Thread; + namespace MouseWithoutBorders { /* Common.DragDrop.cs @@ -238,7 +240,7 @@ internal static void DragDropStep06() internal static void DragDropStep08(DATA package) { - GetNameOfMachineWithClipboardData(package); + Receiver.GetNameOfMachineWithClipboardData(package); Logger.LogDebug("DragDropStep08: ClipboardDragDrop Received. machine with drag file was set"); } diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs index e50e87b8f95e..fc581a3de26a 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs @@ -21,6 +21,8 @@ using MouseWithoutBorders.Core; using MouseWithoutBorders.Form; +using Thread = MouseWithoutBorders.Core.Thread; + namespace MouseWithoutBorders { internal partial class Common @@ -145,7 +147,7 @@ internal static void MouseEvent(MOUSEDATA e, int dx, int dy) } } - private static bool IsSwitchingByMouseEnabled() + internal static bool IsSwitchingByMouseEnabled() { return (EasyMouseOption)Setting.Values.EasyMouse == EasyMouseOption.Enable || InputHook.EasyMouseKeyDown; } diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs index da52a60db2da..b733e17830d0 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs @@ -23,6 +23,8 @@ using MouseWithoutBorders.Form; using Windows.UI.Input.Preview.Injection; +using Thread = MouseWithoutBorders.Core.Thread; + namespace MouseWithoutBorders { internal partial class Common diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs deleted file mode 100644 index 773564fe7f04..000000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Windows.Forms; - -// -// Logging. -// -// -// 2008 created by Truong Do (ductdo). -// 2009-... modified by Truong Do (TruongDo). -// 2023- Included in PowerToys. -// -using MouseWithoutBorders.Class; -using MouseWithoutBorders.Core; -using MouseWithoutBorders.Exceptions; - -namespace MouseWithoutBorders -{ - public class Thread - { - private static readonly Lock ThreadsLock = new(); - private static List threads; - - private readonly System.Threading.Thread thread; - - internal Thread(ThreadStart callback, string name) - { - UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name }); - } - - internal Thread(ParameterizedThreadStart callback, string name) - { - UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name }); - } - - internal static void UpdateThreads(System.Threading.Thread thread) - { - lock (ThreadsLock) - { - bool found = false; - List toBeRemovedThreads = new(); - threads ??= new List(); - - foreach (System.Threading.Thread t in threads) - { - if (!t.IsAlive) - { - toBeRemovedThreads.Add(t); - } - else if (t.ManagedThreadId == thread.ManagedThreadId) - { - found = true; - } - } - - foreach (System.Threading.Thread t in toBeRemovedThreads) - { - _ = threads.Remove(t); - } - - if (!found) - { - threads.Add(thread); - } - } - } - - internal static string DumpThreadsStack() - { - string stack = "\r\nMANAGED THREADS: " + threads.Count.ToString(CultureInfo.InvariantCulture) + "\r\n"; - stack += Logger.GetStackTrace(new StackTrace()); - return stack; - } - - internal void SetApartmentState(ApartmentState apartmentState) - { - thread.SetApartmentState(apartmentState); - } - - internal void Start() - { - thread.Start(); - } - - internal void Start(object parameter) - { - thread.Start(parameter); - } - - internal static void Sleep(int millisecondsTimeout) - { - System.Threading.Thread.Sleep(millisecondsTimeout); - } - - internal static System.Threading.Thread CurrentThread => System.Threading.Thread.CurrentThread; - - internal ThreadPriority Priority - { - get => thread.Priority; - set => thread.Priority = value; - } - - internal System.Threading.ThreadState ThreadState => thread.ThreadState; - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs b/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs index 2072478f2dad..cbf11ca16e0d 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs @@ -51,10 +51,14 @@ internal partial class Common private const int SKIP_PIXELS = 1; private const int JUMP_PIXELS = 2; - private static ID desMachineID; +#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter + internal static ID desMachineID; +#pragma warning restore SA1307 internal static string DesMachineName = string.Empty; private static ID newDesMachineID; - private static ID newDesMachineIdEx; +#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter + internal static ID newDesMachineIdEx; +#pragma warning restore SA1307 private static ID dropMachineID; private static long lastJump = Common.GetTick(); @@ -720,7 +724,7 @@ internal static void RemoveDeadMachines() } } - private static string AddToMachinePool(DATA package) + internal static string AddToMachinePool(DATA package) { // Log("********** AddToMachinePool called: " + package.src.ToString(CultureInfo.InvariantCulture)); diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs deleted file mode 100644 index 5b17801450f0..000000000000 --- a/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs +++ /dev/null @@ -1,431 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Drawing; -using System.Globalization; -using System.IO; -using System.Threading.Tasks; -using System.Windows.Forms; - -// -// Back-end thread for the socket. -// -// -// 2008 created by Truong Do (ductdo). -// 2009-... modified by Truong Do (TruongDo). -// 2023- Included in PowerToys. -// -using MouseWithoutBorders.Class; -using MouseWithoutBorders.Core; - -[module: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "MouseWithoutBorders.Common.#PreProcess(MouseWithoutBorders.DATA)", Justification = "Dotnet port with style preservation")] - -namespace MouseWithoutBorders -{ - internal partial class Common - { - private static readonly uint QUEUE_SIZE = 50; - private static readonly int[] RecentProcessedPackageIDs = new int[QUEUE_SIZE]; - private static int recentProcessedPackageIndex; -#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter - internal static long processedPackageCount; - internal static long skippedPackageCount; -#pragma warning restore SA1307 - - internal static long JustGotAKey { get; set; } - - private static bool PreProcess(DATA package) - { - if (package.Type == PackageType.Invalid) - { - if ((Common.InvalidPackageCount % 100) == 0) - { - ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false); - } - - Common.InvalidPackageCount++; - Logger.Log("Invalid packages received!"); - return false; - } - else if (package.Type == 0) - { - Logger.Log("Got an unknown package!"); - return false; - } - else if (package.Type is not PackageType.ClipboardText and not PackageType.ClipboardImage - - // BEGIN: These package types are sent by TcpSend which is single direction. - and not PackageType.Handshake and not PackageType.HandshakeAck) - { - // END - lock (RecentProcessedPackageIDs) - { - for (int i = 0; i < QUEUE_SIZE; i++) - { - if (RecentProcessedPackageIDs[i] == package.Id) - { - skippedPackageCount++; - return false; - } - } - - processedPackageCount++; - recentProcessedPackageIndex = (int)((recentProcessedPackageIndex + 1) % QUEUE_SIZE); - RecentProcessedPackageIDs[recentProcessedPackageIndex] = package.Id; - } - } - - return true; - } - - private static System.Drawing.Point lastXY; - - internal static void ProcessPackage(DATA package, TcpSk tcp) - { - if (!PreProcess(package)) - { - return; - } - - switch (package.Type) - { - case PackageType.Keyboard: - PackageReceived.Keyboard++; - if (package.Des == MachineID || package.Des == ID.ALL) - { - JustGotAKey = GetTick(); - - // NOTE(@yuyoyuppe): disabled to drop elevation requirement - bool nonElevated = Common.RunWithNoAdminRight && false; - if (nonElevated && Setting.Values.OneWayControlMode) - { - if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) - { - Common.ShowOneWayModeMessage(); - } - - return; - } - - InputSimulation.SendKey(package.Kd); - } - - break; - - case PackageType.Mouse: - PackageReceived.Mouse++; - - if (package.Des == MachineID || package.Des == ID.ALL) - { - if (desMachineID != MachineID) - { - NewDesMachineID = DesMachineID = MachineID; - } - - // NOTE(@yuyoyuppe): disabled to drop elevation requirement - bool nonElevated = Common.RunWithNoAdminRight && false; - if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE) - { - if (!IsDropping) - { - if (package.Md.dwFlags is WM_LBUTTONDOWN or WM_RBUTTONDOWN) - { - Common.ShowOneWayModeMessage(); - } - } - else if (package.Md.dwFlags is WM_LBUTTONUP or WM_RBUTTONUP) - { - IsDropping = false; - } - - return; - } - - if (Math.Abs(package.Md.X) >= MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= MOVE_MOUSE_RELATIVE) - { - if (package.Md.dwFlags == Common.WM_MOUSEMOVE) - { - InputSimulation.MoveMouseRelative( - package.Md.X < 0 ? package.Md.X + MOVE_MOUSE_RELATIVE : package.Md.X - MOVE_MOUSE_RELATIVE, - package.Md.Y < 0 ? package.Md.Y + MOVE_MOUSE_RELATIVE : package.Md.Y - MOVE_MOUSE_RELATIVE); - _ = NativeMethods.GetCursorPos(ref lastXY); - - Point p = MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, MachineID); - - if (!p.IsEmpty) - { - HasSwitchedMachineSinceLastCopy = true; - - Logger.LogDebug(string.Format( - CultureInfo.CurrentCulture, - "***** Controlled Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})", - newDesMachineIdEx, - lastXY.X, - lastXY.Y)); - - SendNextMachine(package.Src, newDesMachineIdEx, p); - } - } - else - { - _ = NativeMethods.GetCursorPos(ref lastXY); - package.Md.X = lastXY.X * 65535 / screenWidth; - package.Md.Y = lastXY.Y * 65535 / screenHeight; - _ = InputSimulation.SendMouse(package.Md); - } - } - else - { - _ = InputSimulation.SendMouse(package.Md); - _ = NativeMethods.GetCursorPos(ref lastXY); - } - - LastX = lastXY.X; - LastY = lastXY.Y; - CustomCursor.ShowFakeMouseCursor(LastX, LastY); - } - - DragDropStep01(package.Md.dwFlags); - DragDropStep09(package.Md.dwFlags); - break; - - case PackageType.NextMachine: - Logger.LogDebug("PackageType.NextMachine received!"); - - if (IsSwitchingByMouseEnabled()) - { - PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y)); - } - - break; - - case PackageType.ExplorerDragDrop: - PackageReceived.ExplorerDragDrop++; - DragDropStep03(package); - break; - - case PackageType.Heartbeat: - case PackageType.Heartbeat_ex: - PackageReceived.Heartbeat++; - - Common.GeneratedKey = Common.GeneratedKey || package.Type == PackageType.Heartbeat_ex; - - if (Common.GeneratedKey) - { - Setting.Values.MyKey = Common.MyKey; - SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2); - } - - string desMachine = Common.AddToMachinePool(package); - - if (Setting.Values.FirstRun && !string.IsNullOrEmpty(desMachine)) - { - Common.UpdateSetupMachineMatrix(desMachine); - Common.UpdateClientSockets("UpdateSetupMachineMatrix"); - } - - break; - - case PackageType.Heartbeat_ex_l2: - Common.GeneratedKey = true; - Setting.Values.MyKey = Common.MyKey; - SendPackage(ID.ALL, PackageType.Heartbeat_ex_l3); - - break; - - case PackageType.Heartbeat_ex_l3: - Common.GeneratedKey = true; - Setting.Values.MyKey = Common.MyKey; - - break; - - case PackageType.Awake: - PackageReceived.Heartbeat++; - _ = Common.AddToMachinePool(package); - Common.HumanBeingDetected(); - break; - - case PackageType.Hello: - PackageReceived.Hello++; - SendHeartBeat(); - string newMachine = Common.AddToMachinePool(package); - if (Setting.Values.MachineMatrixString == null) - { - string tip = newMachine + " saying Hello!"; - tip += "\r\n Right Click to setup your machine Matrix"; - ShowToolTip(tip); - } - - break; - - case PackageType.Hi: - PackageReceived.Hello++; - break; - - case PackageType.ByeBye: - PackageReceived.ByeBye++; - ProcessByeByeMessage(package); - break; - - case PackageType.Clipboard: - PackageReceived.Clipboard++; - if (!RunOnLogonDesktop && !RunOnScrSaverDesktop) - { - clipboardCopiedTime = GetTick(); - GetNameOfMachineWithClipboardData(package); - SignalBigClipboardData(); - } - - break; - - case PackageType.MachineSwitched: - if (GetTick() - clipboardCopiedTime < BIG_CLIPBOARD_DATA_TIMEOUT && (package.Des == MachineID)) - { - clipboardCopiedTime = 0; - Common.GetRemoteClipboard("PackageType.MachineSwitched"); - } - - break; - - case PackageType.ClipboardCapture: - PackageReceived.Clipboard++; - if (!RunOnLogonDesktop && !RunOnScrSaverDesktop) - { - if (package.Des == MachineID || package.Des == ID.ALL) - { - GetNameOfMachineWithClipboardData(package); - GetRemoteClipboard("mspaint," + LastMachineWithClipboardData); - } - } - - break; - - case PackageType.CaptureScreenCommand: - PackageReceived.Clipboard++; - if (package.Des == MachineID || package.Des == ID.ALL) - { - Common.SendImage(package.Src, Common.CaptureScreen()); - } - - break; - - case PackageType.ClipboardAsk: - PackageReceived.ClipboardAsk++; - - if (package.Des == MachineID) - { - _ = Task.Run(() => - { - try - { - System.Threading.Thread thread = Thread.CurrentThread; - thread.Name = $"{nameof(PackageType.ClipboardAsk)}.{thread.ManagedThreadId}"; - Thread.UpdateThreads(thread); - - string remoteMachine = package.MachineName; - System.Net.Sockets.TcpClient client = ConnectToRemoteClipboardSocket(remoteMachine); - bool clientPushData = true; - - if (ShakeHand(ref remoteMachine, client.Client, out Stream enStream, out Stream deStream, ref clientPushData, ref package.PostAction)) - { - SocketStuff.SendClipboardData(client.Client, enStream); - } - } - catch (Exception e) - { - Logger.Log(e); - } - }); - } - - break; - - case PackageType.ClipboardDragDrop: - PackageReceived.ClipboardDragDrop++; - DragDropStep08(package); - break; - - case PackageType.ClipboardDragDropOperation: - PackageReceived.ClipboardDragDrop++; - DragDropStep08_2(package); - break; - - case PackageType.ClipboardDragDropEnd: - PackageReceived.ClipboardDragDropEnd++; - DragDropStep12(); - break; - - case PackageType.ClipboardText: - case PackageType.ClipboardImage: - clipboardCopiedTime = 0; - if (package.Type == PackageType.ClipboardImage) - { - PackageReceived.ClipboardImage++; - } - else - { - PackageReceived.ClipboardText++; - } - - if (tcp != null) - { - Common.ReceiveClipboardDataUsingTCP( - package, - package.Type == PackageType.ClipboardImage, - tcp); - } - - break; - - case PackageType.HideMouse: - HasSwitchedMachineSinceLastCopy = true; - HideMouseCursor(true); - MainFormDotEx(false); - ReleaseAllKeys(); - break; - - default: - if ((package.Type & PackageType.Matrix) == PackageType.Matrix) - { - PackageReceived.Matrix++; - UpdateMachineMatrix(package); - break; - } - else - { - // We should never get to this point! - Logger.Log("Invalid package received!"); - return; - } - } - } - - private static void GetNameOfMachineWithClipboardData(DATA package) - { - LastIDWithClipboardData = package.Src; - List matchingMachines = Common.MachinePool.TryFindMachineByID(LastIDWithClipboardData); - if (matchingMachines.Count >= 1) - { - LastMachineWithClipboardData = matchingMachines[0].Name.Trim(); - } - - /* - lastMachineWithClipboardData = - Common.GetString(BitConverter.GetBytes(package.machineNameHead)); - lastMachineWithClipboardData += - Common.GetString(BitConverter.GetBytes(package.machineNameTail)); - lastMachineWithClipboardData = lastMachineWithClipboardData.Trim(); - * */ - } - - private static void SignalBigClipboardData() - { - Logger.LogDebug("SignalBigClipboardData"); - SetToggleIcon(new int[TOGGLE_ICONS_SIZE] { ICON_BIG_CLIPBOARD, -1, ICON_BIG_CLIPBOARD, -1 }); - } - } -} diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs index 722590ef811a..006c5d862c20 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs @@ -23,6 +23,8 @@ using MouseWithoutBorders.Class; using MouseWithoutBorders.Core; +using Thread = MouseWithoutBorders.Core.Thread; + namespace MouseWithoutBorders { // Desktops, and GetScreenConfig routines diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.cs b/src/modules/MouseWithoutBorders/App/Class/Common.cs index f3cf4a86fde2..1131893ec42c 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.cs @@ -32,6 +32,8 @@ using MouseWithoutBorders.Core; using MouseWithoutBorders.Exceptions; +using Thread = MouseWithoutBorders.Core.Thread; + // Log is enough [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Common.#CheckClipboard()", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Common.#CheckForDesktopSwitchEvent(System.Boolean)", Justification = "Dotnet port with style preservation")] @@ -88,8 +90,10 @@ internal Common() private static FrmInputCallback inputCallbackForm; private static FrmAbout aboutForm; private static Thread helper; - private static int screenWidth; - private static int screenHeight; +#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter + internal static int screenWidth; + internal static int screenHeight; +#pragma warning restore SA1307 private static int lastX; private static int lastY; @@ -552,7 +556,7 @@ internal static void SendAwakeBeat() lastRealInputEventCount = Common.RealInputEventCount; } - private static void HumanBeingDetected() + internal static void HumanBeingDetected() { if (lastInputEventCount == Common.InputEventCount) { @@ -613,7 +617,7 @@ internal static void SendClipboardBeat() SendPackage(ID.ALL, PackageType.Clipboard); } - private static void ProcessByeByeMessage(DATA package) + internal static void ProcessByeByeMessage(DATA package) { if (package.Src == desMachineID) { diff --git a/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs b/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs index ecaeef77db65..9621c54bc411 100644 --- a/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs +++ b/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs @@ -27,6 +27,9 @@ #endif using SystemClipboard = System.Windows.Forms.Clipboard; +#if !MM_HELPER +using Thread = MouseWithoutBorders.Core.Thread; +#endif namespace MouseWithoutBorders { diff --git a/src/modules/MouseWithoutBorders/App/Class/Program.cs b/src/modules/MouseWithoutBorders/App/Class/Program.cs index ac33da9ae983..011b1cfdc975 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Program.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Program.cs @@ -35,6 +35,7 @@ using StreamJsonRpc; using Logger = MouseWithoutBorders.Core.Logger; +using Thread = MouseWithoutBorders.Core.Thread; [module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant", Justification = "Dotnet port with style preservation")] diff --git a/src/modules/MouseWithoutBorders/App/Class/Setting.cs b/src/modules/MouseWithoutBorders/App/Class/Setting.cs index a49b98d4f7c2..23ca49309c49 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Setting.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Setting.cs @@ -13,7 +13,6 @@ using System.Linq; using System.Security.Cryptography; using System.Text.Json.Serialization; -using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; @@ -33,6 +32,8 @@ using MouseWithoutBorders.Core; using Settings.UI.Library.Attributes; +using Lock = System.Threading.Lock; + [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadIntSetting(System.String,System.Int32)", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#SaveSetting(System.String,System.Object)", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadStringSetting(System.String,System.String)", Justification = "Dotnet port with style preservation")] diff --git a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs index 6f354e4af174..31b047a837e5 100644 --- a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs +++ b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs @@ -29,6 +29,8 @@ // using MouseWithoutBorders.Exceptions; +using Thread = MouseWithoutBorders.Core.Thread; + [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.SocketStuff.#SendData(System.Byte[])", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.SocketStuff.#Close()", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.SocketStuff.#CreateSocket(System.Boolean)", Justification = "Dotnet port with style preservation")] @@ -1524,7 +1526,7 @@ private void MainTCPRoutine(TcpSk tcp, string machineName, bool isClient) } else { - Common.ProcessPackage(package, currentTcp); + Receiver.ProcessPackage(package, currentTcp); } } } diff --git a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs index ffff1ce76bf6..f915ae94e057 100644 --- a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs +++ b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs @@ -23,6 +23,8 @@ // using MouseWithoutBorders.Exceptions; +using Thread = MouseWithoutBorders.Core.Thread; + [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.TcpServer.#Close()", Justification = "Dotnet port with style preservation")] namespace MouseWithoutBorders.Class diff --git a/src/modules/MouseWithoutBorders/App/Core/Logger.cs b/src/modules/MouseWithoutBorders/App/Core/Logger.cs index c6e62139ba4a..c561d5ff42da 100644 --- a/src/modules/MouseWithoutBorders/App/Core/Logger.cs +++ b/src/modules/MouseWithoutBorders/App/Core/Logger.cs @@ -15,6 +15,9 @@ using System.Threading; using System.Windows.Forms; +using MouseWithoutBorders.Class; +using MouseWithoutBorders.Exceptions; + // // Logging. // @@ -23,9 +26,6 @@ // 2009-... modified by Truong Do (TruongDo). // 2023- Included in PowerToys. // -using MouseWithoutBorders.Class; -using MouseWithoutBorders.Exceptions; - namespace MouseWithoutBorders.Core; internal static class Logger @@ -163,8 +163,8 @@ internal static void LogAll() Common.PackageReceived.ExplorerDragDrop, Common.invalidPackageCount, Common.PackageReceived.Nil, - Common.processedPackageCount, - Common.skippedPackageCount); + Receiver.processedPackageCount, + Receiver.skippedPackageCount); Log(log); lastPackageReceived = Common.PackageReceived; } @@ -201,6 +201,8 @@ internal static void DumpObjects(int level) _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false); sb.AppendLine("[Logger]\r\n==============="); Logger.DumpType(sb, typeof(Logger), 0, level); + sb.AppendLine("[Receiver]\r\n==============="); + Logger.DumpType(sb, typeof(Receiver), 0, level); log = string.Format( CultureInfo.CurrentCulture, diff --git a/src/modules/MouseWithoutBorders/App/Core/Receiver.cs b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs new file mode 100644 index 000000000000..4ef8a8ccdc6f --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs @@ -0,0 +1,429 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Threading.Tasks; +using System.Windows.Forms; + +using MouseWithoutBorders.Class; + +[module: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "MouseWithoutBorders.Common.#PreProcess(MouseWithoutBorders.DATA)", Justification = "Dotnet port with style preservation")] + +// +// Back-end thread for the socket. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal static class Receiver +{ + private static readonly uint QUEUE_SIZE = 50; + private static readonly int[] RecentProcessedPackageIDs = new int[QUEUE_SIZE]; + private static int recentProcessedPackageIndex; +#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter + internal static long processedPackageCount; + internal static long skippedPackageCount; +#pragma warning restore SA1307 + + private static long JustGotAKey { get; set; } + + private static bool PreProcess(DATA package) + { + if (package.Type == PackageType.Invalid) + { + if ((Common.InvalidPackageCount % 100) == 0) + { + Common.ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false); + } + + Common.InvalidPackageCount++; + Logger.Log("Invalid packages received!"); + return false; + } + else if (package.Type == 0) + { + Logger.Log("Got an unknown package!"); + return false; + } + else if (package.Type is not PackageType.ClipboardText and not PackageType.ClipboardImage + + // BEGIN: These package types are sent by TcpSend which is single direction. + and not PackageType.Handshake and not PackageType.HandshakeAck) + { + // END + lock (RecentProcessedPackageIDs) + { + for (int i = 0; i < QUEUE_SIZE; i++) + { + if (RecentProcessedPackageIDs[i] == package.Id) + { + skippedPackageCount++; + return false; + } + } + + processedPackageCount++; + recentProcessedPackageIndex = (int)((recentProcessedPackageIndex + 1) % QUEUE_SIZE); + RecentProcessedPackageIDs[recentProcessedPackageIndex] = package.Id; + } + } + + return true; + } + + private static System.Drawing.Point lastXY; + + internal static void ProcessPackage(DATA package, TcpSk tcp) + { + if (!PreProcess(package)) + { + return; + } + + switch (package.Type) + { + case PackageType.Keyboard: + Common.PackageReceived.Keyboard++; + if (package.Des == Common.MachineID || package.Des == ID.ALL) + { + JustGotAKey = Common.GetTick(); + + // NOTE(@yuyoyuppe): disabled to drop elevation requirement + bool nonElevated = Common.RunWithNoAdminRight && false; + if (nonElevated && Setting.Values.OneWayControlMode) + { + if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) + { + Common.ShowOneWayModeMessage(); + } + + return; + } + + InputSimulation.SendKey(package.Kd); + } + + break; + + case PackageType.Mouse: + Common.PackageReceived.Mouse++; + + if (package.Des == Common.MachineID || package.Des == ID.ALL) + { + if (Common.desMachineID != Common.MachineID) + { + Common.NewDesMachineID = Common.DesMachineID = Common.MachineID; + } + + // NOTE(@yuyoyuppe): disabled to drop elevation requirement + bool nonElevated = Common.RunWithNoAdminRight && false; + if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE) + { + if (!Common.IsDropping) + { + if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN) + { + Common.ShowOneWayModeMessage(); + } + } + else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP) + { + Common.IsDropping = false; + } + + return; + } + + if (Math.Abs(package.Md.X) >= Common.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Common.MOVE_MOUSE_RELATIVE) + { + if (package.Md.dwFlags == Common.WM_MOUSEMOVE) + { + InputSimulation.MoveMouseRelative( + package.Md.X < 0 ? package.Md.X + Common.MOVE_MOUSE_RELATIVE : package.Md.X - Common.MOVE_MOUSE_RELATIVE, + package.Md.Y < 0 ? package.Md.Y + Common.MOVE_MOUSE_RELATIVE : package.Md.Y - Common.MOVE_MOUSE_RELATIVE); + _ = NativeMethods.GetCursorPos(ref lastXY); + + Point p = Common.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID); + + if (!p.IsEmpty) + { + Common.HasSwitchedMachineSinceLastCopy = true; + + Logger.LogDebug(string.Format( + CultureInfo.CurrentCulture, + "***** Controlled Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})", + Common.newDesMachineIdEx, + lastXY.X, + lastXY.Y)); + + Common.SendNextMachine(package.Src, Common.newDesMachineIdEx, p); + } + } + else + { + _ = NativeMethods.GetCursorPos(ref lastXY); + package.Md.X = lastXY.X * 65535 / Common.screenWidth; + package.Md.Y = lastXY.Y * 65535 / Common.screenHeight; + _ = InputSimulation.SendMouse(package.Md); + } + } + else + { + _ = InputSimulation.SendMouse(package.Md); + _ = NativeMethods.GetCursorPos(ref lastXY); + } + + Common.LastX = lastXY.X; + Common.LastY = lastXY.Y; + CustomCursor.ShowFakeMouseCursor(Common.LastX, Common.LastY); + } + + Common.DragDropStep01(package.Md.dwFlags); + Common.DragDropStep09(package.Md.dwFlags); + break; + + case PackageType.NextMachine: + Logger.LogDebug("PackageType.NextMachine received!"); + + if (Common.IsSwitchingByMouseEnabled()) + { + Common.PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y)); + } + + break; + + case PackageType.ExplorerDragDrop: + Common.PackageReceived.ExplorerDragDrop++; + Common.DragDropStep03(package); + break; + + case PackageType.Heartbeat: + case PackageType.Heartbeat_ex: + Common.PackageReceived.Heartbeat++; + + Common.GeneratedKey = Common.GeneratedKey || package.Type == PackageType.Heartbeat_ex; + + if (Common.GeneratedKey) + { + Setting.Values.MyKey = Common.MyKey; + Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2); + } + + string desMachine = Common.AddToMachinePool(package); + + if (Setting.Values.FirstRun && !string.IsNullOrEmpty(desMachine)) + { + Common.UpdateSetupMachineMatrix(desMachine); + Common.UpdateClientSockets("UpdateSetupMachineMatrix"); + } + + break; + + case PackageType.Heartbeat_ex_l2: + Common.GeneratedKey = true; + Setting.Values.MyKey = Common.MyKey; + Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l3); + + break; + + case PackageType.Heartbeat_ex_l3: + Common.GeneratedKey = true; + Setting.Values.MyKey = Common.MyKey; + + break; + + case PackageType.Awake: + Common.PackageReceived.Heartbeat++; + _ = Common.AddToMachinePool(package); + Common.HumanBeingDetected(); + break; + + case PackageType.Hello: + Common.PackageReceived.Hello++; + Common.SendHeartBeat(); + string newMachine = Common.AddToMachinePool(package); + if (Setting.Values.MachineMatrixString == null) + { + string tip = newMachine + " saying Hello!"; + tip += "\r\n Right Click to setup your machine Matrix"; + Common.ShowToolTip(tip); + } + + break; + + case PackageType.Hi: + Common.PackageReceived.Hello++; + break; + + case PackageType.ByeBye: + Common.PackageReceived.ByeBye++; + Common.ProcessByeByeMessage(package); + break; + + case PackageType.Clipboard: + Common.PackageReceived.Clipboard++; + if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) + { + Common.clipboardCopiedTime = Common.GetTick(); + GetNameOfMachineWithClipboardData(package); + SignalBigClipboardData(); + } + + break; + + case PackageType.MachineSwitched: + if (Common.GetTick() - Common.clipboardCopiedTime < Common.BIG_CLIPBOARD_DATA_TIMEOUT && (package.Des == Common.MachineID)) + { + Common.clipboardCopiedTime = 0; + Common.GetRemoteClipboard("PackageType.MachineSwitched"); + } + + break; + + case PackageType.ClipboardCapture: + Common.PackageReceived.Clipboard++; + if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) + { + if (package.Des == Common.MachineID || package.Des == ID.ALL) + { + GetNameOfMachineWithClipboardData(package); + Common.GetRemoteClipboard("mspaint," + Common.LastMachineWithClipboardData); + } + } + + break; + + case PackageType.CaptureScreenCommand: + Common.PackageReceived.Clipboard++; + if (package.Des == Common.MachineID || package.Des == ID.ALL) + { + Common.SendImage(package.Src, Common.CaptureScreen()); + } + + break; + + case PackageType.ClipboardAsk: + Common.PackageReceived.ClipboardAsk++; + + if (package.Des == Common.MachineID) + { + _ = Task.Run(() => + { + try + { + System.Threading.Thread thread = Thread.CurrentThread; + thread.Name = $"{nameof(PackageType.ClipboardAsk)}.{thread.ManagedThreadId}"; + Thread.UpdateThreads(thread); + + string remoteMachine = package.MachineName; + System.Net.Sockets.TcpClient client = Common.ConnectToRemoteClipboardSocket(remoteMachine); + bool clientPushData = true; + + if (Common.ShakeHand(ref remoteMachine, client.Client, out Stream enStream, out Stream deStream, ref clientPushData, ref package.PostAction)) + { + SocketStuff.SendClipboardData(client.Client, enStream); + } + } + catch (Exception e) + { + Logger.Log(e); + } + }); + } + + break; + + case PackageType.ClipboardDragDrop: + Common.PackageReceived.ClipboardDragDrop++; + Common.DragDropStep08(package); + break; + + case PackageType.ClipboardDragDropOperation: + Common.PackageReceived.ClipboardDragDrop++; + Common.DragDropStep08_2(package); + break; + + case PackageType.ClipboardDragDropEnd: + Common.PackageReceived.ClipboardDragDropEnd++; + Common.DragDropStep12(); + break; + + case PackageType.ClipboardText: + case PackageType.ClipboardImage: + Common.clipboardCopiedTime = 0; + if (package.Type == PackageType.ClipboardImage) + { + Common.PackageReceived.ClipboardImage++; + } + else + { + Common.PackageReceived.ClipboardText++; + } + + if (tcp != null) + { + Common.ReceiveClipboardDataUsingTCP( + package, + package.Type == PackageType.ClipboardImage, + tcp); + } + + break; + + case PackageType.HideMouse: + Common.HasSwitchedMachineSinceLastCopy = true; + Common.HideMouseCursor(true); + Common.MainFormDotEx(false); + Common.ReleaseAllKeys(); + break; + + default: + if ((package.Type & PackageType.Matrix) == PackageType.Matrix) + { + Common.PackageReceived.Matrix++; + Common.UpdateMachineMatrix(package); + break; + } + else + { + // We should never get to this point! + Logger.Log("Invalid package received!"); + return; + } + } + } + + internal static void GetNameOfMachineWithClipboardData(DATA package) + { + Common.LastIDWithClipboardData = package.Src; + List matchingMachines = Common.MachinePool.TryFindMachineByID(Common.LastIDWithClipboardData); + if (matchingMachines.Count >= 1) + { + Common.LastMachineWithClipboardData = matchingMachines[0].Name.Trim(); + } + + /* + lastMachineWithClipboardData = + Common.GetString(BitConverter.GetBytes(package.machineNameHead)); + lastMachineWithClipboardData += + Common.GetString(BitConverter.GetBytes(package.machineNameTail)); + lastMachineWithClipboardData = lastMachineWithClipboardData.Trim(); + * */ + } + + private static void SignalBigClipboardData() + { + Logger.LogDebug("SignalBigClipboardData"); + Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE] { Common.ICON_BIG_CLIPBOARD, -1, Common.ICON_BIG_CLIPBOARD, -1 }); + } +} diff --git a/src/modules/MouseWithoutBorders/App/Core/Thread.cs b/src/modules/MouseWithoutBorders/App/Core/Thread.cs new file mode 100644 index 000000000000..1ce276e9034f --- /dev/null +++ b/src/modules/MouseWithoutBorders/App/Core/Thread.cs @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Threading; + +// +// Logging. +// +// +// 2008 created by Truong Do (ductdo). +// 2009-... modified by Truong Do (TruongDo). +// 2023- Included in PowerToys. +// +namespace MouseWithoutBorders.Core; + +internal sealed class Thread +{ + private static readonly Lock ThreadsLock = new(); + private static List threads; + + private readonly System.Threading.Thread thread; + + internal Thread(ThreadStart callback, string name) + { + UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name }); + } + + internal Thread(ParameterizedThreadStart callback, string name) + { + UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name }); + } + + internal static void UpdateThreads(System.Threading.Thread thread) + { + lock (ThreadsLock) + { + bool found = false; + List toBeRemovedThreads = new(); + threads ??= new List(); + + foreach (System.Threading.Thread t in threads) + { + if (!t.IsAlive) + { + toBeRemovedThreads.Add(t); + } + else if (t.ManagedThreadId == thread.ManagedThreadId) + { + found = true; + } + } + + foreach (System.Threading.Thread t in toBeRemovedThreads) + { + _ = threads.Remove(t); + } + + if (!found) + { + threads.Add(thread); + } + } + } + + internal static string DumpThreadsStack() + { + string stack = "\r\nMANAGED THREADS: " + threads.Count.ToString(CultureInfo.InvariantCulture) + "\r\n"; + stack += Logger.GetStackTrace(new StackTrace()); + return stack; + } + + internal void SetApartmentState(ApartmentState apartmentState) + { + thread.SetApartmentState(apartmentState); + } + + internal void Start() + { + thread.Start(); + } + + internal void Start(object parameter) + { + thread.Start(parameter); + } + + internal static void Sleep(int millisecondsTimeout) + { + System.Threading.Thread.Sleep(millisecondsTimeout); + } + + internal static System.Threading.Thread CurrentThread => System.Threading.Thread.CurrentThread; + + internal ThreadPriority Priority + { + get => thread.Priority; + set => thread.Priority = value; + } + + internal System.Threading.ThreadState ThreadState => thread.ThreadState; +} diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt index 1a20c67b31d6..dddef136c481 100644 --- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt +++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt @@ -4,20 +4,28 @@ [Other Logs] =============== = MouseWithoutBorders.Common -lastClipboardEventTime = 0 -clipboardCopiedTime = 0 Comma = System.Char[] --System.Char[] = System.Char[]: N/A Star = System.Char[] --System.Char[] = System.Char[]: N/A NullSeparator = System.Char[] --System.Char[] = System.Char[]: N/A +lastClipboardEventTime = 0 +clipboardCopiedTime = 0 k__BackingField = NONE k__BackingField = 0 k__BackingField = False lastClipboardObject = k__BackingField = False -ClipboardThreadOldLock = O +ClipboardThreadOldLock = Lock +--_owningThreadId = 0 +--_state = 0 +--_recursionCount = 0 +--_spinCount = 22 +--_waiterStartTimeMs = 0 +--s_contentionCount = 0 +--s_maxSpinCount = 22 +--s_minSpinCountForAdaptiveSpin = -100 screenWidth = 0 screenHeight = 0 lastX = 0 @@ -43,7 +51,15 @@ socketMutexBalance = 0 k__BackingField = False k__BackingField = 0 k__BackingField = 0 -InputSimulationLock = O +InputSimulationLock = Lock +--_owningThreadId = 0 +--_state = 0 +--_recursionCount = 0 +--_spinCount = 22 +--_waiterStartTimeMs = 0 +--s_contentionCount = 0 +--s_maxSpinCount = 22 +--s_minSpinCountForAdaptiveSpin = -100 lastSendNextMachine = 0 lastInputEventCount = 0 lastRealInputEventCount = 0 @@ -85,15 +101,7 @@ LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte ------[5] = 0 ------[6] = 0 ------[7] = 0 -------[8] = 0 -------[9] = 0 -------[10] = 0 -------[11] = 0 -------[12] = 0 -------[13] = 0 -------[14] = 0 -------[15] = 0 ---_budget = 2 +--_budget = ???????????? --_growLockArray = True --_comparerIsDefaultForClasses = False KeybdPackage = MouseWithoutBorders.DATA @@ -155,7 +163,15 @@ ReopenSocketDueToReadError = False --MaxValue = 31/12/9999 23:59:59 --UnixEpoch = 01/01/1970 00:00:00 lastReleaseAllKeysCall = 0 -McMatrixLock = O +McMatrixLock = Lock +--_owningThreadId = 0 +--_state = 0 +--_recursionCount = 0 +--_spinCount = 22 +--_waiterStartTimeMs = 0 +--s_contentionCount = 0 +--s_maxSpinCount = 22 +--s_minSpinCountForAdaptiveSpin = -100 desMachineID = NONE DesMachineName = newDesMachineID = NONE @@ -207,66 +223,6 @@ PackageReceived = MouseWithoutBorders.PackageMonitor --ExplorerDragDrop = 0 --Nil = 0 PackageID = 0 -QUEUE_SIZE = 50 -RecentProcessedPackageIDs = 32[] ---[0] = 0 ---[1] = 0 ---[2] = 0 ---[3] = 0 ---[4] = 0 ---[5] = 0 ---[6] = 0 ---[7] = 0 ---[8] = 0 ---[9] = 0 ---[10] = 0 ---[11] = 0 ---[12] = 0 ---[13] = 0 ---[14] = 0 ---[15] = 0 ---[16] = 0 ---[17] = 0 ---[18] = 0 ---[19] = 0 ---[20] = 0 ---[21] = 0 ---[22] = 0 ---[23] = 0 ---[24] = 0 ---[25] = 0 ---[26] = 0 ---[27] = 0 ---[28] = 0 ---[29] = 0 ---[30] = 0 ---[31] = 0 ---[32] = 0 ---[33] = 0 ---[34] = 0 ---[35] = 0 ---[36] = 0 ---[37] = 0 ---[38] = 0 ---[39] = 0 ---[40] = 0 ---[41] = 0 ---[42] = 0 ---[43] = 0 ---[44] = 0 ---[45] = 0 ---[46] = 0 ---[47] = 0 ---[48] = 0 ---[49] = 0 -recentProcessedPackageIndex = 0 -processedPackageCount = 0 -skippedPackageCount = 0 -k__BackingField = 0 -lastXY = {X=0,Y=0} ---x = 0 ---y = 0 ---Empty = {X=0,Y=0} shownErrMessage = False lastStartServiceTime = ???????????? --_dateData = ???????????? @@ -334,9 +290,17 @@ WM_KEYDOWN = 256 WM_KEYUP = 257 WM_SYSKEYDOWN = 260 WM_SYSKEYUP = 261 -[Logger Logs] +[Logger] =============== -AllLogsLock = O +AllLogsLock = Lock +--_owningThreadId = 0 +--_state = 0 +--_recursionCount = 0 +--_spinCount = 22 +--_waiterStartTimeMs = 0 +--s_contentionCount = 0 +--s_maxSpinCount = 22 +--s_minSpinCountForAdaptiveSpin = -100 LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32] --_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,32] ----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalComparer @@ -354,15 +318,7 @@ LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32] ------[5] = 0 ------[6] = 0 ------[7] = 0 -------[8] = 0 -------[9] = 0 -------[10] = 0 -------[11] = 0 -------[12] = 0 -------[13] = 0 -------[14] = 0 -------[15] = 0 ---_budget = 2 +--_budget = ???????????? --_growLockArray = True --_comparerIsDefaultForClasses = False allLogsIndex = 0 @@ -402,3 +358,65 @@ MAX_LOG = 10000 MaxLogExceptionPerHour = 1000 HeaderSENT = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13} HeaderRECEIVED = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15} +[Receiver] +=============== +QUEUE_SIZE = 50 +RecentProcessedPackageIDs = 32[] +--[0] = 0 +--[1] = 0 +--[2] = 0 +--[3] = 0 +--[4] = 0 +--[5] = 0 +--[6] = 0 +--[7] = 0 +--[8] = 0 +--[9] = 0 +--[10] = 0 +--[11] = 0 +--[12] = 0 +--[13] = 0 +--[14] = 0 +--[15] = 0 +--[16] = 0 +--[17] = 0 +--[18] = 0 +--[19] = 0 +--[20] = 0 +--[21] = 0 +--[22] = 0 +--[23] = 0 +--[24] = 0 +--[25] = 0 +--[26] = 0 +--[27] = 0 +--[28] = 0 +--[29] = 0 +--[30] = 0 +--[31] = 0 +--[32] = 0 +--[33] = 0 +--[34] = 0 +--[35] = 0 +--[36] = 0 +--[37] = 0 +--[38] = 0 +--[39] = 0 +--[40] = 0 +--[41] = 0 +--[42] = 0 +--[43] = 0 +--[44] = 0 +--[45] = 0 +--[46] = 0 +--[47] = 0 +--[48] = 0 +--[49] = 0 +recentProcessedPackageIndex = 0 +processedPackageCount = 0 +skippedPackageCount = 0 +k__BackingField = 0 +lastXY = {X=0,Y=0} +--x = 0 +--y = 0 +--Empty = {X=0,Y=0} diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs index be960b9a9b92..a3d3a173f185 100644 --- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs +++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs @@ -62,6 +62,7 @@ static string NormalizeLog(string log) "lastJump = ", "lastStartServiceTime = ", "InitialIV = ", + "--_budget = ", }; for (var i = 0; i < lines.Length; i++) { @@ -89,6 +90,10 @@ static string NormalizeLog(string log) "------[13] = 0", "------[14] = 0", "------[15] = 0", + "------[16] = 0", + "------[17] = 0", + "------[18] = 0", + "------[19] = 0", }; lines = lines.Where(line => !removeLines.Contains(line)).ToArray(); @@ -113,8 +118,10 @@ static string NormalizeLog(string log) var sb = new StringBuilder(1000000); _ = Logger.PrivateDump(sb, Logger.AllLogs, "[Program logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false); _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false); - sb.AppendLine("[Logger Logs]\r\n==============="); + sb.AppendLine("[Logger]\r\n==============="); Logger.DumpType(sb, typeof(Logger), 0, settingsDumpObjectsLevel); + sb.AppendLine("[Receiver]\r\n==============="); + Logger.DumpType(sb, typeof(Receiver), 0, settingsDumpObjectsLevel); var actual = sb.ToString(); expected = NormalizeLog(expected); @@ -146,8 +153,6 @@ static string NormalizeLog(string log) message.AppendLine(CultureInfo.InvariantCulture, $"[{j}]: {expectedLines[j]}:"); } - var x = new ConcurrentDictionary(-1, 16); - Assert.Fail(message.ToString()); } } From 458e5c5509e8d6c45190ff1b525fbfa67c0a0361 Mon Sep 17 00:00:00 2001 From: Nathan Gill Date: Fri, 17 Jan 2025 16:13:41 +0000 Subject: [PATCH 082/103] [PTRun]Add setting for different trigonometric units in Calculator (#36717) * Added angle units to PowerToys Run Calculator plugin. * Update Resources.resx * Added GitHub SpellCheck rule for 'gradians'. --------- Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> --- .github/actions/spell-check/expect.txt | 107 +----------------- .../ExtendedCalculatorParserTests.cs | 62 ++++++++++ .../CalculateEngine.cs | 10 ++ .../CalculateHelper.cs | 86 ++++++++++++++ .../Main.cs | 26 +++++ .../Properties/Resources.Designer.cs | 45 ++++++++ .../Properties/Resources.resx | 20 ++++ 7 files changed, 250 insertions(+), 106 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index c80245750072..325b984c1cd3 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -4,12 +4,10 @@ abgr ABlocked ABOUTBOX Abug -accctrl Acceleratorkeys ACCEPTFILES ACCESSDENIED ACCESSTOKEN -aclapi AClient AColumn acrt @@ -54,12 +52,9 @@ APIENTRY APIIs Apm APPBARDATA -appdata APPEXECLINK -Appium APPLICATIONFRAMEHOST appmanifest -appmodel APPNAME appref appsettings @@ -83,11 +78,7 @@ ASSOCSTR ASYNCWINDOWPLACEMENT ASYNCWINDOWPOS atl -atlbase -atlcom atleast -atlfile -atlstr ATRIOX aumid Authenticode @@ -135,7 +126,6 @@ bmi bms BNumber BODGY -bootstrapper BOOTSTRAPPERINSTALLFOLDER bostrot BOTTOMALIGN @@ -163,7 +153,6 @@ CALG callbackptr calpwstr Cangjie -caniuse CANRENAME CAPTUREBLT CAPTURECHANGED @@ -178,11 +167,9 @@ CDeclaration CDEF CElems CENTERALIGN -ceq certlm certmgr cfp -cguid CHANGECBCHAIN changecursor CHILDACTIVATE @@ -207,19 +194,16 @@ CLSCTX Clusion cmder CMDNOTFOUNDMODULEINTERFACE -Cmds CMIC CMINVOKECOMMANDINFO CMINVOKECOMMANDINFOEX CMock CMONITORS cmph -cne CNF coclass codereview Codespaces -codicon COINIT colorconv colorformat @@ -231,18 +215,12 @@ comdef comdlg comexp cominterop -commandline -commctrl -commdlg compmgmt COMPOSITIONFULL -comutil CONFIGW CONFLICTINGMODIFIERKEY CONFLICTINGMODIFIERSHORTCUT CONOUT -consts -contentdialog contentfiles CONTEXTHELP CONTEXTMENUHANDLER @@ -257,7 +235,6 @@ countof cph cplusplus CPower -cppwinrt createdump CREATEPROCESS CREATESCHEDULEDTASK @@ -267,8 +244,6 @@ CRECT CRH critsec Crossdevice -CRSEL -crx CSearch CSettings cso @@ -306,11 +281,8 @@ DBLEPSILON DCapture DCBA DCOM -dcommon -dcomp DComposition DCR -DCs ddd DDEIf DDevice @@ -345,7 +317,6 @@ DESIGNINFO DESKTOPABSOLUTEEDITING DESKTOPABSOLUTEPARSING desktopshorcutinstalled -desktopwindowxamlsource devblogs devdocs devenum @@ -353,7 +324,6 @@ devmgmt DEVMODE DEVMODEW DEVMON -devpkey DEVSOURCE DGR DIALOGEX @@ -423,8 +393,6 @@ DWORDLONG dworigin dwrite dxgi -dxgidebug -dxgiformat easeofaccess ecount EData @@ -434,15 +402,12 @@ EDITSHORTCUTS EDITTEXT EFile ekus -emmintrin -Emoji ENABLEDELAYEDEXPANSION ENABLEDPOPUP ENABLETAB ENABLETEMPLATE encodedlaunch encryptor -endpointvolume ENDSESSION ENSUREVISIBLE ENTERSIZEMOVE @@ -466,7 +431,6 @@ eula eurochange eventlog eventvwr -evntrace evt EWXFORCE EWXFORCEIFHUNG @@ -478,7 +442,6 @@ examplehandler examplepowertoy EXAND EXCLUDEFROMCAPTURE -exdisp executionpolicy exename EXITSIZEMOVE @@ -541,7 +504,6 @@ frm Froml FROMTOUCH fsmgmt -Functiondiscoverykeys FZE gacutil Gaeilge @@ -576,10 +538,10 @@ gpo GPOCA gpp gpu +gradians GSM gtm guiddata -guiddef GUITHREADINFO GValue gwl @@ -626,7 +588,6 @@ Hif HIMAGELIST himl hinst -hinstance HIWORD HKCC HKCOMB @@ -659,7 +620,6 @@ hrgn hsb HSCROLL hsi -hstring HTCLIENT hthumbnail HTOUCHINPUT @@ -737,14 +697,12 @@ installscopeperuser INSTALLSTARTMENUSHORTCUT INSTALLSTATE Inste -Intelli Interlop INTRESOURCE INVALIDARG invalidoperatioexception ipcmanager IPREVIEW -ipreviewhandlervisualssetfont irprops isbi ISearch @@ -769,7 +727,6 @@ jpe jpnime Jsons jsonval -junja jxr keybd KEYBDDATA @@ -787,7 +744,6 @@ keyvault KILLFOCUS killrunner kmph -Knownfolders KSPROPERTY Kybd lastcodeanalysissucceeded @@ -818,7 +774,6 @@ LIVEZOOM lld LLKH llkhf -lmcons LMEM LMENU lnks @@ -861,7 +816,6 @@ lprc LPSAFEARRAY lpstr lpsz -lpt LPTHREAD LPTOP lptpm @@ -920,18 +874,13 @@ MERGECOPY MERGEPAINT Metadatas metafile -mfapi mfc -mfidl -mfobjects mfplat -mftransform Mgmt mic midl mii mindaro -Minimatch Minimizable MINIMIZEBOX MINIMIZEEND @@ -946,10 +895,8 @@ mlcfg mmc mmcexe MMdd -mmdeviceapi mmi mmsys -mmsystem mockapi MODALFRAME MODESPRUNED @@ -976,7 +923,6 @@ mscorlib msctls msdata MSDL -msedge MSGFLT msiexec MSIFASTINSTALL @@ -1030,7 +976,6 @@ netframework netsetup netsh newcolor -newdev NEWDIALOGSTYLE NEWFILE newitem @@ -1057,7 +1002,6 @@ NOCOPYBITS NOCOPYSECURITYATTRIBS NOCRLF nodeca -nodoc NODRAWCAPTION NODRAWICON NOINHERITLAYOUT @@ -1095,7 +1039,6 @@ NOTIFICATIONSDLL NOTIFYICONDATA NOTIFYICONDATAW NOTIMPL -notlike NOTOPMOST NOTRACK NOTSRCCOPY @@ -1108,15 +1051,12 @@ NResize nsunt NTAPI ntdll -ntfs NTSTATUS NTSYSAPI NULLCURSOR nullonfailure numberbox nwc -Objbase -objidl ocr Ocrsettings odbccp @@ -1148,7 +1088,6 @@ osvi OUTOFCONTEXT outpin Outptr -outputtype outsettings OVERLAPPEDWINDOW overlaywindow @@ -1167,7 +1106,6 @@ PARENTRELATIVEPARSING parray PARTIALCONFIRMATIONDIALOGTITLE PATCOPY -pathcch PATHMUSTEXIST PATINVERT PATPAINT @@ -1255,7 +1193,6 @@ pptal ppv prc Prefixer -Preinstalled prependpath prevhost previewer @@ -1272,7 +1209,6 @@ prm proactively PROCESSENTRY PROCESSKEY -processthreadsapi PROCESSTRACE procmon PRODEXT @@ -1282,7 +1218,6 @@ programdata projectname PROPBAG PROPERTYKEY -propkey PROPVARIANT propvarutil PRTL @@ -1346,7 +1281,6 @@ rectp RECTSOURCE recyclebin Redist -redistributable reencode reencoded REFCLSID @@ -1375,10 +1309,8 @@ remoteip Removelnk renamable RENAMEONCOLLISION -Renamer reparented reparenting -reparse reportfileaccesses requery requerying @@ -1390,7 +1322,6 @@ RESIZETOFIT resmimetype RESOURCEID RESTORETOMAXIMIZED -restrictederrorinfo resultlist RETURNONLYFSDIRS RGBQUAD @@ -1405,7 +1336,6 @@ riid ringbuffer RKey RNumber -roadmap rop ROUNDSMALL rpcrt @@ -1418,14 +1348,12 @@ rstringalpha rstringdigit RTB RTLREADING -ruleset runas rundll rungameid RUNLEVEL runtimeclass runtimepack -runtimes ruuid rvm rwin @@ -1486,21 +1414,17 @@ SHCNE SHCNF SHCONTF Shcore -shellapi SHELLDETAILS SHELLDLL shellex SHELLEXECUTEINFO SHELLEXECUTEINFOW -shellscalingapi SHFILEINFO SHFILEOPSTRUCT SHGDN SHGDNF SHGFI shinfo -shldisp -shlobj shlwapi shmem SHNAMEMAPPING @@ -1628,7 +1552,6 @@ SVGIn SVGIO svgz SVSI -SWC SWFO SWP SWRESTORE @@ -1652,8 +1575,6 @@ SYSMENU SYSTEMAPPS SYSTEMMODAL SYSTEMTIME -tailwindcss -tapp TApplication TApplied targ @@ -1694,7 +1615,6 @@ THH THICKFRAME THISCOMPONENT THotkey -thumbcache TILEDWINDOW TILLSON timedate @@ -1708,17 +1628,14 @@ tkconverters TLayout tlb tlbimp -tlhelp TMPVAR TNP Toolhelp toolkitconverters -Toolset toolwindow TOPDOWNDIB TOUCHEVENTF TOUCHINPUT -touchpad TRACEHANDLE tracelogging tracerpt @@ -1731,7 +1648,6 @@ triaging trl trx tsa -Tsd TServer tstoi TStr @@ -1761,15 +1677,11 @@ UNCPRIORITY UNDNAME unhiding UNICODETEXT -uninstantiated -uniquifier Uniquifies unitconverter unittests -Unknwn UNLEN UNORM -unregistering unremapped unvirtualized unwide @@ -1783,11 +1695,9 @@ updown UPGRADINGPRODUCTCODE Uptool urld -urlmon Usb USEDEFAULT USEFILEATTRIBUTES -USERDATA USESHOWWINDOW USESTDHANDLES USRDLL @@ -1814,7 +1724,6 @@ vdupq VERBSONLY VERBW VERIFYCONTEXT -verrsrc VERSIONINFO VERTRES VERTSIZE @@ -1862,7 +1771,6 @@ WANTPALM wbem WBounds Wca -wcautil WCE wcex WClass @@ -1884,10 +1792,7 @@ wifi wil winapi winappsdk -wincodec -Wincodecsdk wincolor -windef windir WINDOWCREATED WINDOWEDGE @@ -1896,18 +1801,12 @@ WINDOWNAME WINDOWPLACEMENT WINDOWPOSCHANGED WINDOWPOSCHANGING -windowsapp WINDOWSBUILDNUMBER windowssearch windowssettings WINDOWSTYLES WINDOWSTYLESICON -windowsx -winerror WINEVENT -winevt -winexe -winforms winget wingetcreate Winhook @@ -1918,9 +1817,7 @@ WINNT winres winrt winsdk -winsdkver winsta -winternl WINTHRESHOLD WINVER winxamlmanager @@ -1966,14 +1863,12 @@ wrl wscui wsf wsh -wsl wstr wsz WTA WTNCA wtoi WTS -wtsapi WTSAT Wubi WVC diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest/ExtendedCalculatorParserTests.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest/ExtendedCalculatorParserTests.cs index b13072021b24..594773c36bc8 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest/ExtendedCalculatorParserTests.cs +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator.UnitTest/ExtendedCalculatorParserTests.cs @@ -279,5 +279,67 @@ public void Interpret_TestScientificNotation_WhenCalled(string input, string sou Assert.IsNotNull(result); Assert.AreEqual(expectedResult, result.Result); } + + [DataTestMethod] + [DataRow("sin(90)", "sin((pi / 180) * (90))")] + [DataRow("arcsin(0.5)", "(180 / pi) * (arcsin(0.5))")] + [DataRow("sin(sin(30))", "sin((pi / 180) * (sin((pi / 180) * (30))))")] + [DataRow("cos(tan(45))", "cos((pi / 180) * (tan((pi / 180) * (45))))")] + [DataRow("arctan(sin(30))", "(180 / pi) * (arctan(sin((pi / 180) * (30))))")] + [DataRow("sin(cos(tan(30)))", "sin((pi / 180) * (cos((pi / 180) * (tan((pi / 180) * (30))))))")] + [DataRow("sin(arcsin(0.5))", "sin((pi / 180) * ((180 / pi) * (arcsin(0.5))))")] + [DataRow("sin(30) + cos(60)", "sin((pi / 180) * (30)) + cos((pi / 180) * (60))")] + [DataRow("sin(30 + 15)", "sin((pi / 180) * (30 + 15))")] + [DataRow("sin(45) * cos(45) - tan(30)", "sin((pi / 180) * (45)) * cos((pi / 180) * (45)) - tan((pi / 180) * (30))")] + [DataRow("arcsin(arccos(0.5))", "(180 / pi) * (arcsin((180 / pi) * (arccos(0.5))))")] + [DataRow("sin(sin(sin(30)))", "sin((pi / 180) * (sin((pi / 180) * (sin((pi / 180) * (30))))))")] + [DataRow("log(10)", "log(10)")] + [DataRow("sin(30) + pi", "sin((pi / 180) * (30)) + pi")] + [DataRow("sin(-30)", "sin((pi / 180) * (-30))")] + [DataRow("sin((30))", "sin((pi / 180) * ((30)))")] + [DataRow("arcsin(1) * 2", "(180 / pi) * (arcsin(1)) * 2")] + [DataRow("cos(1/2)", "cos((pi / 180) * (1/2))")] + [DataRow("sin ( 90 )", "sin ((pi / 180) * ( 90 ))")] + [DataRow("cos(arcsin(sin(45)))", "cos((pi / 180) * ((180 / pi) * (arcsin(sin((pi / 180) * (45))))))")] + public void UpdateTrigFunctions_Degrees(string input, string expectedResult) + { + // Call UpdateTrigFunctions in degrees mode + string result = CalculateHelper.UpdateTrigFunctions(input, CalculateEngine.TrigMode.Degrees); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedResult, result); + } + + [DataTestMethod] + [DataRow("sin(90)", "sin((pi / 200) * (90))")] + [DataRow("arcsin(0.5)", "(200 / pi) * (arcsin(0.5))")] + [DataRow("sin(sin(30))", "sin((pi / 200) * (sin((pi / 200) * (30))))")] + [DataRow("cos(tan(45))", "cos((pi / 200) * (tan((pi / 200) * (45))))")] + [DataRow("arctan(sin(30))", "(200 / pi) * (arctan(sin((pi / 200) * (30))))")] + [DataRow("sin(cos(tan(30)))", "sin((pi / 200) * (cos((pi / 200) * (tan((pi / 200) * (30))))))")] + [DataRow("sin(arcsin(0.5))", "sin((pi / 200) * ((200 / pi) * (arcsin(0.5))))")] + [DataRow("sin(30) + cos(60)", "sin((pi / 200) * (30)) + cos((pi / 200) * (60))")] + [DataRow("sin(30 + 15)", "sin((pi / 200) * (30 + 15))")] + [DataRow("sin(45) * cos(45) - tan(30)", "sin((pi / 200) * (45)) * cos((pi / 200) * (45)) - tan((pi / 200) * (30))")] + [DataRow("arcsin(arccos(0.5))", "(200 / pi) * (arcsin((200 / pi) * (arccos(0.5))))")] + [DataRow("sin(sin(sin(30)))", "sin((pi / 200) * (sin((pi / 200) * (sin((pi / 200) * (30))))))")] + [DataRow("log(10)", "log(10)")] + [DataRow("sin(30) + pi", "sin((pi / 200) * (30)) + pi")] + [DataRow("sin(-30)", "sin((pi / 200) * (-30))")] + [DataRow("sin((30))", "sin((pi / 200) * ((30)))")] + [DataRow("arcsin(1) * 2", "(200 / pi) * (arcsin(1)) * 2")] + [DataRow("cos(1/2)", "cos((pi / 200) * (1/2))")] + [DataRow("sin ( 90 )", "sin ((pi / 200) * ( 90 ))")] + [DataRow("cos(arcsin(sin(45)))", "cos((pi / 200) * ((200 / pi) * (arcsin(sin((pi / 200) * (45))))))")] + public void UpdateTrigFunctions_Gradians(string input, string expectedResult) + { + // Call UpdateTrigFunctions in gradians mode + string result = CalculateHelper.UpdateTrigFunctions(input, CalculateEngine.TrigMode.Gradians); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(expectedResult, result); + } } } diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs index 815a52d8b0b5..9248e3ca89b0 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs @@ -23,6 +23,13 @@ public class CalculateEngine public const int RoundingDigits = 10; + public enum TrigMode + { + Radians, + Degrees, + Gradians, + } + /// /// Interpret /// @@ -52,6 +59,9 @@ public CalculateResult Interpret(string input, CultureInfo cultureInfo, out stri input = CalculateHelper.FixHumanMultiplicationExpressions(input); + // Modify trig functions depending on angle unit setting + input = CalculateHelper.UpdateTrigFunctions(input, Main.GetTrigMode()); + var result = _magesEngine.Interpret(input); // This could happen for some incorrect queries, like pi(2) diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs index 436591e3b333..95705a34ca13 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs @@ -25,6 +25,11 @@ public static class CalculateHelper @")+$", RegexOptions.Compiled); + private const string DegToRad = "(pi / 180) * "; + private const string GradToRad = "(pi / 200) * "; + private const string RadToDeg = "(180 / pi) * "; + private const string RadToGrad = "(200 / pi) * "; + public static bool InputValid(string input) { if (string.IsNullOrWhiteSpace(input)) @@ -204,5 +209,86 @@ private static string CheckConstantThenConstant(string input) return output; } + + // Gets the index of the closing bracket of a function + private static int FindClosingBracketIndex(string input, int start) + { + int bracketCount = 0; // Set count to zero + for (int i = start; i < input.Length; i++) + { + if (input[i] == '(') + { + bracketCount++; + } + else if (input[i] == ')') + { + bracketCount--; + if (bracketCount == 0) + { + return i; + } + } + } + + return -1; // Unmatched brackets + } + + private static string ModifyTrigFunction(string input, string function, string modification) + { + // Get the RegEx pattern to match, depending on whether the function is inverse or normal + string pattern = function.StartsWith("arc", StringComparison.Ordinal) ? string.Empty : @"(? Resources.wox_plugin_calculator_plugin_name; @@ -67,6 +69,20 @@ public class Main : IPlugin, IPluginI18n, IDisposable, ISettingProvider DisplayDescription = Resources.wox_plugin_calculator_replace_input_description, Value = true, }, + new PluginAdditionalOption + { + Key = TrigMode, + DisplayLabel = Resources.wox_plugin_calculator_trig_unit_mode, + DisplayDescription = Resources.wox_plugin_calculator_trig_unit_mode_description, + PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Combobox, + ComboBoxValue = (int)CalculateEngine.TrigMode.Radians, + ComboBoxItems = + [ + new KeyValuePair(Resources.wox_plugin_calculator_trig_unit_radians, "0"), + new KeyValuePair(Resources.wox_plugin_calculator_trig_unit_degrees, "1"), + new KeyValuePair(Resources.wox_plugin_calculator_trig_unit_gradians, "2"), + ], + }, }; public List Query(Query query) @@ -183,6 +199,7 @@ public void UpdateSettings(PowerLauncherPluginSettings settings) var inputUseEnglishFormat = false; var outputUseEnglishFormat = false; var replaceInput = true; + var trigMode = CalculateEngine.TrigMode.Radians; if (settings != null && settings.AdditionalOptions != null) { @@ -194,11 +211,20 @@ public void UpdateSettings(PowerLauncherPluginSettings settings) var optionReplaceInput = settings.AdditionalOptions.FirstOrDefault(x => x.Key == ReplaceInput); replaceInput = optionReplaceInput?.Value ?? replaceInput; + + var optionTrigMode = settings.AdditionalOptions.FirstOrDefault(x => x.Key == TrigMode); + trigMode = (CalculateEngine.TrigMode)int.Parse(optionTrigMode.ComboBoxValue.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); } _inputUseEnglishFormat = inputUseEnglishFormat; _outputUseEnglishFormat = outputUseEnglishFormat; _replaceInput = replaceInput; + _trigMode = trigMode; + } + + public static CalculateEngine.TrigMode GetTrigMode() + { + return _trigMode; } public void Dispose() diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs index b48a3f417ec3..861993dbdd33 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.Designer.cs @@ -203,5 +203,50 @@ public static string wox_plugin_calculator_replace_input_description { return ResourceManager.GetString("wox_plugin_calculator_replace_input_description", resourceCulture); } } + + /// + /// Looks up a localized string similar to Degrees. + /// + public static string wox_plugin_calculator_trig_unit_degrees { + get { + return ResourceManager.GetString("wox_plugin_calculator_trig_unit_degrees", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gradians. + /// + public static string wox_plugin_calculator_trig_unit_gradians { + get { + return ResourceManager.GetString("wox_plugin_calculator_trig_unit_gradians", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trigonometry Unit. + /// + public static string wox_plugin_calculator_trig_unit_mode { + get { + return ResourceManager.GetString("wox_plugin_calculator_trig_unit_mode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies the angle unit to use for trigonometry operations.. + /// + public static string wox_plugin_calculator_trig_unit_mode_description { + get { + return ResourceManager.GetString("wox_plugin_calculator_trig_unit_mode_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Radians. + /// + public static string wox_plugin_calculator_trig_unit_radians { + get { + return ResourceManager.GetString("wox_plugin_calculator_trig_unit_radians", resourceCulture); + } + } } } diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.resx b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.resx index 727603ab04d6..3c56eedf4b5d 100644 --- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.resx +++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/Properties/Resources.resx @@ -167,4 +167,24 @@ When using direct activation, appending '=' to the expression will replace the input with the calculated result (e.g. '=5*3-2=' will change the query to '=13'). + + Trigonometry Unit + Title text for trig unit mode. + + + Specifies the angle unit to use for trigonometry operations + Description text for trig mode setting. + + + Radians + Text for angle unit. + + + Degrees + Text to use for angle unit. + + + Gradians + Text for angle unit. + \ No newline at end of file From 5b2e42b5a39bc94d7ee651848df0765e607c1435 Mon Sep 17 00:00:00 2001 From: Jaime Bernardo Date: Fri, 17 Jan 2025 22:10:50 +0000 Subject: [PATCH 083/103] [ci]Remove steps to build abstracted utilities packages (#36934) --- .../ESRPSigning_abstracted_utils_dll.json | 52 ---------- .pipelines/v2/templates/job-build-project.yml | 97 ------------------- 2 files changed, 149 deletions(-) delete mode 100644 .pipelines/ESRPSigning_abstracted_utils_dll.json diff --git a/.pipelines/ESRPSigning_abstracted_utils_dll.json b/.pipelines/ESRPSigning_abstracted_utils_dll.json deleted file mode 100644 index 7655bbee5628..000000000000 --- a/.pipelines/ESRPSigning_abstracted_utils_dll.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "Version": "1.0.0", - "UseMinimatch": false, - "SignBatches": [ - { - "MatchedPath": [ - "PowerToys.HostsUILib.dll", - "PowerToys.EnvironmentVariablesUILib.dll", - "PowerToys.RegistryPreviewUILib.dll" - ], - "SigningInfo": { - "Operations": [ - { - "KeyCode": "CP-230012", - "OperationSetCode": "SigntoolSign", - "Parameters": [ - { - "parameterName": "OpusName", - "parameterValue": "Microsoft" - }, - { - "parameterName": "OpusInfo", - "parameterValue": "http://www.microsoft.com" - }, - { - "parameterName": "FileDigest", - "parameterValue": "/fd \"SHA256\"" - }, - { - "parameterName": "PageHash", - "parameterValue": "/NPH" - }, - { - "parameterName": "TimeStamp", - "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - } - ], - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-230012", - "OperationSetCode": "SigntoolVerify", - "Parameters": [], - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] - } - } - ] -} diff --git a/.pipelines/v2/templates/job-build-project.yml b/.pipelines/v2/templates/job-build-project.yml index 5a3b787ede41..f55d9f71a9fc 100644 --- a/.pipelines/v2/templates/job-build-project.yml +++ b/.pipelines/v2/templates/job-build-project.yml @@ -242,103 +242,6 @@ jobs: env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - ${{ if eq(parameters.codeSign, true) }}: - - template: steps-esrp-signing.yml - parameters: - displayName: Sign Utilities - signingIdentity: ${{ parameters.signingIdentity }} - inputs: - FolderPath: 'src/modules' - signType: batchSigning - batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_abstracted_utils_dll.json' - ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' - - - task: VSBuild@1 - displayName: Create Hosts File Editor package - inputs: - solution: '**\HostsUILib.csproj' - vsVersion: 17.0 - msbuildArgs: >- - /p:CIBuild=true;NoBuild=true -t:pack - /bl:$(LogOutputDirectory)\build-hosts.binlog - /p:NoWarn=NU5104 - $(RestoreAdditionalProjectSourcesArg) - configuration: $(BuildConfiguration) - msbuildArchitecture: x64 - maximumCpuCount: true - ${{ if eq(parameters.enableMsBuildCaching, true) }}: - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - - task: VSBuild@1 - displayName: Create Environment Variables Editor package - inputs: - solution: '**\EnvironmentVariablesUILib.csproj' - vsVersion: 17.0 - msbuildArgs: >- - /p:CIBuild=true;NoBuild=true -t:pack - /bl:$(LogOutputDirectory)\build-env-var-editor.binlog - /p:NoWarn=NU5104 - $(RestoreAdditionalProjectSourcesArg) - configuration: $(BuildConfiguration) - msbuildArchitecture: x64 - maximumCpuCount: true - ${{ if eq(parameters.enableMsBuildCaching, true) }}: - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - - task: VSBuild@1 - displayName: Create Registry Preview package - inputs: - solution: '**\RegistryPreviewUILib.csproj' - vsVersion: 17.0 - msbuildArgs: >- - /p:CIBuild=true;NoBuild=true -t:pack - /bl:$(LogOutputDirectory)\build-registry-preview.binlog - /p:NoWarn=NU5104 - $(RestoreAdditionalProjectSourcesArg) - configuration: $(BuildConfiguration) - msbuildArchitecture: x64 - maximumCpuCount: true - ${{ if eq(parameters.enableMsBuildCaching, true) }}: - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - - task: CopyFiles@2 - displayName: Stage NuGet packages - inputs: - contents: "**/bin/Release/PowerToys*.nupkg" - flattenFolders: True - targetFolder: $(JobOutputDirectory)/nupkg - - - ${{ if eq(parameters.codeSign, true) }}: - - template: steps-esrp-signing.yml - parameters: - displayName: Sign NuGet packages - signingIdentity: ${{ parameters.signingIdentity }} - inputs: - FolderPath: $(JobOutputDirectory)/nupkg - Pattern: '*.nupkg' - UseMinimatch: true - signConfigType: inlineSignParams - inlineOperation: >- - [ - { - "KeyCode": "CP-401405", - "OperationCode": "NuGetSign", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-401405", - "OperationCode": "NuGetVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] - - task: VSBuild@1 displayName: Build BugReportTool inputs: From 403060e10982efbb91cbd06f5e4fe2811cb58165 Mon Sep 17 00:00:00 2001 From: Heiko <61519853+htcfreek@users.noreply.github.com> Date: Sun, 19 Jan 2025 15:32:46 +0100 Subject: [PATCH 084/103] [Settings]Update GPO infobar icon, improve some pages and fix bugs (#33703) * changes part 1 * fix xaml code * changes part 2 * fix cmdNotFound page * Update PowerOcrPage * More Pages changed * More Pages changed * revert temporary change * fix spelling * add resw comment * add resw comment * Update MouseWihtoutBorderPage.xaml * PowerPreview page * workspaces page * fix awake page gpo handling * NewPlus page * update new+ page! * AdvancedPaste.xaml: Move Info bar. * Update MouseJumpPanel.xaml * Update GeneralPage.xaml * fix position of info bar and some ui quirks * fix xaml style * fix string resources * string changes * prepare megre main * update new+ page * zoomit page * various fixes --- .../SettingsXAML/Panels/MouseJumpPanel.xaml | 8 +++- .../SettingsXAML/Views/AdvancedPaste.xaml | 33 ++++++++++----- .../SettingsXAML/Views/AlwaysOnTopPage.xaml | 6 ++- .../SettingsXAML/Views/AwakePage.xaml | 6 ++- .../SettingsXAML/Views/AwakePage.xaml.cs | 2 +- .../SettingsXAML/Views/CmdNotFoundPage.xaml | 40 ++++++++++++++----- .../SettingsXAML/Views/ColorPickerPage.xaml | 6 ++- .../SettingsXAML/Views/CropAndLockPage.xaml | 6 ++- .../Views/EnvironmentVariablesPage.xaml | 6 ++- .../SettingsXAML/Views/FancyZonesPage.xaml | 6 ++- .../SettingsXAML/Views/FileLocksmithPage.xaml | 6 ++- .../SettingsXAML/Views/GeneralPage.xaml | 37 ++++++++++------- .../SettingsXAML/Views/HostsPage.xaml | 6 ++- .../SettingsXAML/Views/ImageResizerPage.xaml | 6 ++- .../Views/KeyboardManagerPage.xaml | 6 ++- .../SettingsXAML/Views/MeasureToolPage.xaml | 6 ++- .../SettingsXAML/Views/MouseUtilsPage.xaml | 18 +++++++-- .../Views/MouseWithoutBordersPage.xaml | 22 +++++----- .../SettingsXAML/Views/NewPlusPage.xaml | 11 +++-- .../SettingsXAML/Views/PeekPage.xaml | 6 ++- .../SettingsXAML/Views/PowerAccentPage.xaml | 6 ++- .../SettingsXAML/Views/PowerLauncherPage.xaml | 12 +++++- .../SettingsXAML/Views/PowerOcrPage.xaml | 19 +++++---- .../SettingsXAML/Views/PowerPreviewPage.xaml | 12 +++++- .../SettingsXAML/Views/PowerRenamePage.xaml | 6 ++- .../Views/RegistryPreviewPage.xaml | 6 ++- .../SettingsXAML/Views/ShortcutGuidePage.xaml | 6 ++- .../SettingsXAML/Views/WorkspacesPage.xaml | 6 ++- .../SettingsXAML/Views/ZoomItPage.xaml | 26 ++++++------ .../Settings.UI/Strings/en-us/Resources.resw | 11 +++++ .../Settings.UI/ViewModels/AwakeViewModel.cs | 27 ++++++++++++- .../ViewModels/CmdNotFoundViewModel.cs | 19 +++++---- .../ViewModels/PowerOcrViewModel.cs | 6 +++ 33 files changed, 305 insertions(+), 100 deletions(-) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Panels/MouseJumpPanel.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Panels/MouseJumpPanel.xaml index b92cf4d4584b..22d996efb288 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Panels/MouseJumpPanel.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Panels/MouseJumpPanel.xaml @@ -35,7 +35,11 @@ IsClosable="False" IsOpen="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay}" IsTabStop="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay}" - Severity="Informational" /> + Severity="Informational"> + + + + - \ No newline at end of file + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml index 391a974efc90..f6308feba6bc 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AdvancedPaste.xaml @@ -56,9 +56,23 @@ IsClosable="False" IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}" IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}" - Severity="Informational" /> + Severity="Informational"> + + + + + + + + + @@ -81,12 +95,6 @@ - - + Severity="Informational"> + + + + + + + + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml index aead2cb5ebfb..66cf570af055 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AlwaysOnTopPage.xaml @@ -27,7 +27,11 @@ IsClosable="False" IsOpen="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}" IsTabStop="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}" - Severity="Informational" /> + Severity="Informational"> + + + + + Severity="Informational"> + + + + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs index 49861c3c0b49..3399f425ccd2 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/AwakePage.xaml.cs @@ -164,7 +164,7 @@ private void UpdateEnabledState(bool recommendedState) { // Get the enabled state from GPO. ViewModel.IsEnabledGpoConfigured = true; - ViewModel.IsEnabled = enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled; + ViewModel.EnabledGPOConfiguration = enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled; } else { diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml index 649d30622617..5c4a09a9c47f 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/CmdNotFoundPage.xaml @@ -21,16 +21,29 @@ + IsOpen="{x:Bind ViewModel.IsModuleGpoEnabled, Mode=OneWay}" + IsTabStop="{x:Bind ViewModel.IsModuleGpoEnabled, Mode=OneWay}" + Severity="Informational"> + + + + + + + + + @@ -45,13 +58,17 @@ AutomationProperties.AccessibilityView="Raw" Foreground="{ThemeResource SystemFillColorSuccessBrush}" Glyph="" /> - +