AlwaysOnTopViewModel.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; 6 using System.Collections.Generic; 7 using System.Globalization; 8 using System.Linq; 9 using System.Runtime.CompilerServices; 10 using System.Text.Json; 11 using global::PowerToys.GPOWrapper; 12 using ManagedCommon; 13 using Microsoft.PowerToys.Settings.UI.Helpers; 14 using Microsoft.PowerToys.Settings.UI.Library; 15 using Microsoft.PowerToys.Settings.UI.Library.Helpers; 16 using Microsoft.PowerToys.Settings.UI.Library.Interfaces; 17 using Microsoft.PowerToys.Settings.UI.Library.Utilities; 18 using Microsoft.PowerToys.Settings.UI.SerializationContext; 19 20 namespace Microsoft.PowerToys.Settings.UI.ViewModels 21 { 22 public partial class AlwaysOnTopViewModel : PageViewModelBase 23 { 24 protected override string ModuleName => AlwaysOnTopSettings.ModuleName; 25 26 private SettingsUtils SettingsUtils { get; set; } 27 28 private GeneralSettings GeneralSettingsConfig { get; set; } 29 30 private AlwaysOnTopSettings Settings { get; set; } 31 32 private Func<string, int> SendConfigMSG { get; } 33 34 public AlwaysOnTopViewModel(SettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<AlwaysOnTopSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc) 35 { 36 ArgumentNullException.ThrowIfNull(settingsUtils); 37 38 SettingsUtils = settingsUtils; 39 40 // To obtain the general settings configurations of PowerToys Settings. 41 ArgumentNullException.ThrowIfNull(settingsRepository); 42 43 GeneralSettingsConfig = settingsRepository.SettingsConfig; 44 45 InitializeEnabledValue(); 46 47 // To obtain the settings configurations of AlwaysOnTop. 48 ArgumentNullException.ThrowIfNull(moduleSettingsRepository); 49 50 Settings = moduleSettingsRepository.SettingsConfig; 51 52 _hotkey = Settings.Properties.Hotkey.Value; 53 _frameEnabled = Settings.Properties.FrameEnabled.Value; 54 _frameThickness = Settings.Properties.FrameThickness.Value; 55 _frameColor = Settings.Properties.FrameColor.Value; 56 _frameOpacity = Settings.Properties.FrameOpacity.Value; 57 _frameAccentColor = Settings.Properties.FrameAccentColor.Value; 58 _soundEnabled = Settings.Properties.SoundEnabled.Value; 59 _doNotActivateOnGameMode = Settings.Properties.DoNotActivateOnGameMode.Value; 60 _roundCornersEnabled = Settings.Properties.RoundCornersEnabled.Value; 61 _excludedApps = Settings.Properties.ExcludedApps.Value; 62 _windows11 = OSVersionHelper.IsWindows11(); 63 64 // set the callback functions value to handle outgoing IPC message. 65 SendConfigMSG = ipcMSGCallBackFunc; 66 } 67 68 private void InitializeEnabledValue() 69 { 70 _enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue(); 71 if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled) 72 { 73 // Get the enabled state from GPO. 74 _enabledStateIsGPOConfigured = true; 75 _isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled; 76 } 77 else 78 { 79 _isEnabled = GeneralSettingsConfig.Enabled.AlwaysOnTop; 80 } 81 } 82 83 public override Dictionary<string, HotkeySettings[]> GetAllHotkeySettings() 84 { 85 var hotkeysDict = new Dictionary<string, HotkeySettings[]> 86 { 87 [ModuleName] = [Hotkey], 88 }; 89 90 return hotkeysDict; 91 } 92 93 public bool IsEnabled 94 { 95 get => _isEnabled; 96 97 set 98 { 99 if (_enabledStateIsGPOConfigured) 100 { 101 // If it's GPO configured, shouldn't be able to change this state. 102 return; 103 } 104 105 if (value != _isEnabled) 106 { 107 _isEnabled = value; 108 109 // Set the status in the general settings configuration 110 GeneralSettingsConfig.Enabled.AlwaysOnTop = value; 111 OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig); 112 113 SendConfigMSG(snd.ToString()); 114 OnPropertyChanged(nameof(IsEnabled)); 115 } 116 } 117 } 118 119 public bool IsEnabledGpoConfigured 120 { 121 get => _enabledStateIsGPOConfigured; 122 } 123 124 public HotkeySettings Hotkey 125 { 126 get => _hotkey; 127 128 set 129 { 130 if (value != _hotkey) 131 { 132 _hotkey = value ?? AlwaysOnTopProperties.DefaultHotkeyValue; 133 134 Settings.Properties.Hotkey.Value = _hotkey; 135 NotifyPropertyChanged(); 136 137 // Also notify that transparency keys have changed 138 OnPropertyChanged(nameof(IncreaseOpacityKeysList)); 139 OnPropertyChanged(nameof(DecreaseOpacityKeysList)); 140 141 // Using InvariantCulture as this is an IPC message 142 SendConfigMSG( 143 string.Format( 144 CultureInfo.InvariantCulture, 145 "{{ \"powertoys\": {{ \"{0}\": {1} }} }}", 146 AlwaysOnTopSettings.ModuleName, 147 JsonSerializer.Serialize(Settings, SourceGenerationContextContext.Default.AlwaysOnTopSettings))); 148 } 149 } 150 } 151 152 public bool FrameEnabled 153 { 154 get => _frameEnabled; 155 156 set 157 { 158 if (value != _frameEnabled) 159 { 160 _frameEnabled = value; 161 Settings.Properties.FrameEnabled.Value = value; 162 NotifyPropertyChanged(); 163 } 164 } 165 } 166 167 public int FrameThickness 168 { 169 get => _frameThickness; 170 171 set 172 { 173 if (value != _frameThickness) 174 { 175 _frameThickness = value; 176 Settings.Properties.FrameThickness.Value = value; 177 NotifyPropertyChanged(); 178 } 179 } 180 } 181 182 public string FrameColor 183 { 184 get => _frameColor; 185 186 set 187 { 188 if (value != _frameColor) 189 { 190 _frameColor = value; 191 Settings.Properties.FrameColor.Value = value; 192 NotifyPropertyChanged(); 193 } 194 } 195 } 196 197 public int FrameOpacity 198 { 199 get => _frameOpacity; 200 201 set 202 { 203 if (value != _frameOpacity) 204 { 205 _frameOpacity = value; 206 Settings.Properties.FrameOpacity.Value = value; 207 NotifyPropertyChanged(); 208 } 209 } 210 } 211 212 public bool SoundEnabled 213 { 214 get => _soundEnabled; 215 216 set 217 { 218 if (value != _soundEnabled) 219 { 220 _soundEnabled = value; 221 Settings.Properties.SoundEnabled.Value = value; 222 NotifyPropertyChanged(); 223 } 224 } 225 } 226 227 public bool DoNotActivateOnGameMode 228 { 229 get => _doNotActivateOnGameMode; 230 231 set 232 { 233 if (value != _doNotActivateOnGameMode) 234 { 235 _doNotActivateOnGameMode = value; 236 Settings.Properties.DoNotActivateOnGameMode.Value = value; 237 NotifyPropertyChanged(); 238 } 239 } 240 } 241 242 public bool RoundCornersEnabled 243 { 244 get => _roundCornersEnabled; 245 246 set 247 { 248 if (value != _roundCornersEnabled) 249 { 250 _roundCornersEnabled = value; 251 Settings.Properties.RoundCornersEnabled.Value = value; 252 NotifyPropertyChanged(); 253 } 254 } 255 } 256 257 public string ExcludedApps 258 { 259 get => _excludedApps; 260 261 set 262 { 263 if (value != _excludedApps) 264 { 265 _excludedApps = value; 266 Settings.Properties.ExcludedApps.Value = value; 267 NotifyPropertyChanged(); 268 } 269 } 270 } 271 272 public bool FrameAccentColor 273 { 274 get => _frameAccentColor; 275 276 set 277 { 278 if (value != _frameAccentColor) 279 { 280 _frameAccentColor = value; 281 Settings.Properties.FrameAccentColor.Value = value; 282 NotifyPropertyChanged(); 283 } 284 } 285 } 286 287 public bool Windows11 288 { 289 get => _windows11; 290 291 set 292 { 293 _windows11 = value; 294 } 295 } 296 297 /// <summary> 298 /// Gets the keys list for increasing window opacity (modifier keys + "+"). 299 /// </summary> 300 public List<object> IncreaseOpacityKeysList 301 { 302 get 303 { 304 var keys = GetModifierKeysList(); 305 keys.Add("+"); 306 return keys; 307 } 308 } 309 310 /// <summary> 311 /// Gets the keys list for decreasing window opacity (modifier keys + "-"). 312 /// </summary> 313 public List<object> DecreaseOpacityKeysList 314 { 315 get 316 { 317 var keys = GetModifierKeysList(); 318 keys.Add("-"); 319 return keys; 320 } 321 } 322 323 /// <summary> 324 /// Gets only the modifier keys from the current hotkey setting. 325 /// </summary> 326 private List<object> GetModifierKeysList() 327 { 328 var modifierKeys = new List<object>(); 329 330 if (_hotkey.Win) 331 { 332 modifierKeys.Add(92); // The Windows key 333 } 334 335 if (_hotkey.Ctrl) 336 { 337 modifierKeys.Add("Ctrl"); 338 } 339 340 if (_hotkey.Alt) 341 { 342 modifierKeys.Add("Alt"); 343 } 344 345 if (_hotkey.Shift) 346 { 347 modifierKeys.Add(16); // The Shift key 348 } 349 350 return modifierKeys; 351 } 352 353 public void NotifyPropertyChanged([CallerMemberName] string propertyName = null) 354 { 355 OnPropertyChanged(propertyName); 356 SettingsUtils.SaveSettings(Settings.ToJsonString(), AlwaysOnTopSettings.ModuleName); 357 } 358 359 public void RefreshEnabledState() 360 { 361 InitializeEnabledValue(); 362 OnPropertyChanged(nameof(IsEnabled)); 363 } 364 365 private GpoRuleConfigured _enabledGpoRuleConfiguration; 366 private bool _enabledStateIsGPOConfigured; 367 private bool _isEnabled; 368 private HotkeySettings _hotkey; 369 private bool _frameEnabled; 370 private int _frameThickness; 371 private string _frameColor; 372 private bool _frameAccentColor; 373 private int _frameOpacity; 374 private bool _soundEnabled; 375 private bool _doNotActivateOnGameMode; 376 private bool _roundCornersEnabled; 377 private string _excludedApps; 378 private bool _windows11; 379 } 380 }