/ src / modules / launcher / Plugins / Microsoft.Plugin.WindowWalker / Components / WindowWalkerSettings.cs
WindowWalkerSettings.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Linq; 7 using System.Runtime.CompilerServices; 8 9 using Microsoft.Plugin.WindowWalker.Properties; 10 using Microsoft.PowerToys.Settings.UI.Library; 11 12 [assembly: InternalsVisibleTo("Microsoft.Plugin.WindowWalker.UnitTests")] 13 14 namespace Microsoft.Plugin.WindowWalker.Components 15 { 16 /// <summary> 17 /// Additional settings for the WindowWalker plugin. 18 /// </summary> 19 /// <remarks>Some code parts reused from TimeZone plugin.</remarks> 20 internal sealed class WindowWalkerSettings 21 { 22 /// <summary> 23 /// Are the class properties initialized with default values 24 /// </summary> 25 private readonly bool _initialized; 26 27 /// <summary> 28 /// An instance of the class <see cref="WindowWalkerSettings"></see> 29 /// </summary> 30 private static WindowWalkerSettings instance; 31 32 /// <summary> 33 /// Gets a value indicating whether we only search for windows on the currently visible desktop or on all desktops. 34 /// </summary> 35 internal bool ResultsFromVisibleDesktopOnly { get; private set; } 36 37 /// <summary> 38 /// Gets a value indicating whether the process id is shown in the subtitle. 39 /// </summary> 40 internal bool SubtitleShowPid { get; private set; } 41 42 /// <summary> 43 /// Gets a value indicating whether the desktop name is shown in the subtitle. 44 /// We don't show the desktop name if there is only one desktop. 45 /// </summary> 46 internal bool SubtitleShowDesktopName { get; private set; } 47 48 /// <summary> 49 /// Gets a value indicating whether we request a confirmation when the user kills a process. 50 /// </summary> 51 internal bool ConfirmKillProcess { get; private set; } 52 53 /// <summary> 54 /// Gets a value indicating whether to kill the entire process tree or the selected process only. 55 /// </summary> 56 internal bool KillProcessTree { get; private set; } 57 58 /// <summary> 59 /// Gets a value indicating whether PowerToys run should stay open after executing killing process and closing window. 60 /// </summary> 61 internal bool OpenAfterKillAndClose { get; private set; } 62 63 /// <summary> 64 /// Gets a value indicating whether the "kill process" command is hidden on processes that require additional permissions (UAC). 65 /// </summary> 66 internal bool HideKillProcessOnElevatedProcesses { get; private set; } 67 68 /// <summary> 69 /// Gets a value indicating whether we show the explorer settings info or not. 70 /// </summary> 71 internal bool HideExplorerSettingInfo { get; private set; } 72 73 /// <summary> 74 /// Initializes a new instance of the <see cref="WindowWalkerSettings"/> class. 75 /// Private constructor to make sure there is never more than one instance of this class 76 /// </summary> 77 private WindowWalkerSettings() 78 { 79 // Init class properties with default values 80 UpdateSettings(null); 81 _initialized = true; 82 } 83 84 /// <summary> 85 /// Gets an instance property of this class that makes sure that the first instance gets created 86 /// and that all the requests end up at that one instance. 87 /// The benefit of this is that we don't need additional variables/parameters 88 /// to communicate the settings between plugin's classes/methods. 89 /// We can simply access this one instance, whenever we need the actual settings. 90 /// </summary> 91 internal static WindowWalkerSettings Instance 92 { 93 get 94 { 95 if (instance == null) 96 { 97 instance = new WindowWalkerSettings(); 98 } 99 100 return instance; 101 } 102 } 103 104 /// <summary> 105 /// Return a list with all additional plugin options. 106 /// </summary> 107 /// <returns>A list with all additional plugin options.</returns> 108 internal static List<PluginAdditionalOption> GetAdditionalOptions() 109 { 110 var optionList = new List<PluginAdditionalOption> 111 { 112 new PluginAdditionalOption 113 { 114 Key = nameof(ResultsFromVisibleDesktopOnly), 115 DisplayLabel = Resources.wox_plugin_windowwalker_SettingResultsVisibleDesktop, 116 Value = false, 117 }, 118 new PluginAdditionalOption 119 { 120 Key = nameof(SubtitleShowPid), 121 DisplayLabel = Resources.wox_plugin_windowwalker_SettingSubtitlePid, 122 Value = false, 123 }, 124 new PluginAdditionalOption 125 { 126 Key = nameof(SubtitleShowDesktopName), 127 DisplayLabel = Resources.wox_plugin_windowwalker_SettingSubtitleDesktopName, 128 DisplayDescription = Resources.wox_plugin_windowwalker_SettingSubtitleDesktopName_Description, 129 Value = true, 130 }, 131 new PluginAdditionalOption 132 { 133 Key = nameof(ConfirmKillProcess), 134 DisplayLabel = Resources.wox_plugin_windowwalker_SettingConfirmKillProcess, 135 Value = true, 136 }, 137 new PluginAdditionalOption 138 { 139 Key = nameof(KillProcessTree), 140 DisplayLabel = Resources.wox_plugin_windowwalker_SettingKillProcessTree, 141 DisplayDescription = Resources.wox_plugin_windowwalker_SettingKillProcessTree_Description, 142 Value = false, 143 }, 144 new PluginAdditionalOption 145 { 146 Key = nameof(OpenAfterKillAndClose), 147 DisplayLabel = Resources.wox_plugin_windowwalker_SettingOpenAfterKillAndClose, 148 DisplayDescription = Resources.wox_plugin_windowwalker_SettingOpenAfterKillAndClose_Description, 149 Value = false, 150 }, 151 new PluginAdditionalOption 152 { 153 Key = nameof(HideKillProcessOnElevatedProcesses), 154 DisplayLabel = Resources.wox_plugin_windowwalker_SettingHideKillProcess, 155 Value = false, 156 }, 157 new PluginAdditionalOption 158 { 159 Key = nameof(HideExplorerSettingInfo), 160 DisplayLabel = Resources.wox_plugin_windowwalker_SettingExplorerSettingInfo, 161 DisplayDescription = Resources.wox_plugin_windowwalker_SettingExplorerSettingInfo_Description, 162 Value = false, 163 }, 164 }; 165 166 return optionList; 167 } 168 169 /// <summary> 170 /// Update this settings. 171 /// </summary> 172 /// <param name="settings">The settings for all power launcher plugins.</param> 173 internal void UpdateSettings(PowerLauncherPluginSettings settings) 174 { 175 if ((settings is null || settings.AdditionalOptions is null) & _initialized) 176 { 177 return; 178 } 179 180 ResultsFromVisibleDesktopOnly = GetSettingOrDefault(settings, nameof(ResultsFromVisibleDesktopOnly)); 181 SubtitleShowPid = GetSettingOrDefault(settings, nameof(SubtitleShowPid)); 182 SubtitleShowDesktopName = GetSettingOrDefault(settings, nameof(SubtitleShowDesktopName)); 183 ConfirmKillProcess = GetSettingOrDefault(settings, nameof(ConfirmKillProcess)); 184 KillProcessTree = GetSettingOrDefault(settings, nameof(KillProcessTree)); 185 OpenAfterKillAndClose = GetSettingOrDefault(settings, nameof(OpenAfterKillAndClose)); 186 HideKillProcessOnElevatedProcesses = GetSettingOrDefault(settings, nameof(HideKillProcessOnElevatedProcesses)); 187 HideExplorerSettingInfo = GetSettingOrDefault(settings, nameof(HideExplorerSettingInfo)); 188 } 189 190 /// <summary> 191 /// Return one <see cref="bool"/> setting of the given settings list with the given name. 192 /// </summary> 193 /// <param name="settings">The object that contain all settings.</param> 194 /// <param name="name">The name of the setting.</param> 195 /// <returns>A settings value.</returns> 196 private static bool GetSettingOrDefault(PowerLauncherPluginSettings settings, string name) 197 { 198 var option = settings?.AdditionalOptions?.FirstOrDefault(x => x.Key == name); 199 200 // If a setting isn't available, we use the value defined in the method GetAdditionalOptions() as fallback. 201 // We can use First() instead of FirstOrDefault() because the values must exist. Otherwise, we made a mistake when defining the settings. 202 return option?.Value ?? GetAdditionalOptions().First(x => x.Key == name).Value; 203 } 204 } 205 }