chore: import upstream snapshot with attribution
Spell checking / Check Spelling (push) Has been cancelled
Spell checking / Update PR (push) Has been cancelled
Publish Dev Docs Website / build (push) Failing after 1s
Publish Dev Docs Website / deploy (push) Has been skipped
Spell checking / Report (Push) (push) Has been cancelled
Spell checking / Report (PR) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:16:02 +08:00
commit 79031da543
8235 changed files with 1365916 additions and 0 deletions
@@ -0,0 +1,23 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library
{
/// <summary>
/// Supported AI service types for PowerToys AI experiences.
/// </summary>
public enum AIServiceType
{
Unknown = 0,
OpenAI,
AzureOpenAI,
Onnx,
ML,
FoundryLocal,
Mistral,
Google,
AzureAIInference,
Ollama,
}
}
@@ -0,0 +1,79 @@
// 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;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public static class AIServiceTypeExtensions
{
/// <summary>
/// Convert a persisted string value into an <see cref="AIServiceType"/>.
/// Supports historical casing and aliases.
/// </summary>
public static AIServiceType ToAIServiceType(this string serviceType)
{
if (string.IsNullOrWhiteSpace(serviceType))
{
return AIServiceType.OpenAI;
}
var normalized = serviceType.Trim().ToLowerInvariant();
return normalized switch
{
"openai" => AIServiceType.OpenAI,
"azureopenai" or "azure" => AIServiceType.AzureOpenAI,
"onnx" => AIServiceType.Onnx,
"foundrylocal" or "foundry" or "fl" => AIServiceType.FoundryLocal,
"ml" or "windowsml" or "winml" => AIServiceType.ML,
"mistral" => AIServiceType.Mistral,
"google" or "googleai" or "googlegemini" => AIServiceType.Google,
"azureaiinference" or "azureinference" => AIServiceType.AzureAIInference,
"ollama" => AIServiceType.Ollama,
_ => AIServiceType.Unknown,
};
}
/// <summary>
/// Convert an <see cref="AIServiceType"/> to the canonical string used for persistence.
/// </summary>
public static string ToConfigurationString(this AIServiceType serviceType)
{
return serviceType switch
{
AIServiceType.OpenAI => "OpenAI",
AIServiceType.AzureOpenAI => "AzureOpenAI",
AIServiceType.Onnx => "Onnx",
AIServiceType.FoundryLocal => "FoundryLocal",
AIServiceType.ML => "ML",
AIServiceType.Mistral => "Mistral",
AIServiceType.Google => "Google",
AIServiceType.AzureAIInference => "AzureAIInference",
AIServiceType.Ollama => "Ollama",
AIServiceType.Unknown => string.Empty,
_ => throw new ArgumentOutOfRangeException(nameof(serviceType), serviceType, "Unsupported AI service type."),
};
}
/// <summary>
/// Convert an <see cref="AIServiceType"/> into the normalized key used internally.
/// </summary>
public static string ToNormalizedKey(this AIServiceType serviceType)
{
return serviceType switch
{
AIServiceType.OpenAI => "openai",
AIServiceType.AzureOpenAI => "azureopenai",
AIServiceType.Onnx => "onnx",
AIServiceType.FoundryLocal => "foundrylocal",
AIServiceType.ML => "ml",
AIServiceType.Mistral => "mistral",
AIServiceType.Google => "google",
AIServiceType.AzureAIInference => "azureaiinference",
AIServiceType.Ollama => "ollama",
_ => string.Empty,
};
}
}
}
@@ -0,0 +1,44 @@
// 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.Linq;
namespace Microsoft.PowerToys.Settings.UI.Library
{
/// <summary>
/// Metadata information for an AI service type.
/// </summary>
public class AIServiceTypeMetadata
{
public AIServiceType ServiceType { get; init; }
public string DisplayName { get; init; }
public string IconPath { get; init; }
public bool IsOnlineService { get; init; }
public bool IsAvailableInUI { get; init; } = true;
public bool IsLocalModel { get; init; }
public string LegalDescription { get; init; }
public string TermsLabel { get; init; }
public Uri TermsUri { get; init; }
public string PrivacyLabel { get; init; }
public Uri PrivacyUri { get; init; }
public bool HasLegalInfo => !string.IsNullOrWhiteSpace(LegalDescription);
public bool HasTermsLink => TermsUri is not null && !string.IsNullOrEmpty(TermsLabel);
public bool HasPrivacyLink => PrivacyUri is not null && !string.IsNullOrEmpty(PrivacyLabel);
}
}
@@ -0,0 +1,189 @@
// 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.Linq;
namespace Microsoft.PowerToys.Settings.UI.Library;
/// <summary>
/// Centralized registry for AI service type metadata.
/// </summary>
public static class AIServiceTypeRegistry
{
private static readonly Dictionary<AIServiceType, AIServiceTypeMetadata> MetadataMap = new()
{
[AIServiceType.AzureAIInference] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.AzureAIInference,
DisplayName = "Azure AI Inference",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/Azure.svg",
IsOnlineService = true,
LegalDescription = "AdvancedPaste_AzureAIInference_LegalDescription",
TermsLabel = "AdvancedPaste_AzureAIInference_TermsLabel",
TermsUri = new Uri("https://azure.microsoft.com/support/legal/"),
PrivacyLabel = "AdvancedPaste_AzureAIInference_PrivacyLabel",
PrivacyUri = new Uri("https://privacy.microsoft.com/privacystatement"),
},
[AIServiceType.AzureOpenAI] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.AzureOpenAI,
DisplayName = "Azure OpenAI",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/AzureAI.svg",
IsOnlineService = true,
LegalDescription = "AdvancedPaste_AzureOpenAI_LegalDescription",
TermsLabel = "AdvancedPaste_AzureOpenAI_TermsLabel",
TermsUri = new Uri("https://azure.microsoft.com/support/legal/"),
PrivacyLabel = "AdvancedPaste_AzureOpenAI_PrivacyLabel",
PrivacyUri = new Uri("https://privacy.microsoft.com/privacystatement"),
},
[AIServiceType.FoundryLocal] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.FoundryLocal,
DisplayName = "Foundry Local",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/FoundryLocal.svg",
IsOnlineService = false,
IsLocalModel = true,
LegalDescription = "AdvancedPaste_FoundryLocal_LegalDescription", // Resource key for localized description
},
[AIServiceType.Google] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.Google,
DisplayName = "Google",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/Gemini.svg",
IsOnlineService = true,
LegalDescription = "AdvancedPaste_Google_LegalDescription",
TermsLabel = "AdvancedPaste_Google_TermsLabel",
TermsUri = new Uri("https://ai.google.dev/gemini-api/terms"),
PrivacyLabel = "AdvancedPaste_Google_PrivacyLabel",
PrivacyUri = new Uri("https://support.google.com/gemini/answer/13594961"),
},
[AIServiceType.Mistral] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.Mistral,
DisplayName = "Mistral",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/Mistral.svg",
IsOnlineService = true,
LegalDescription = "AdvancedPaste_Mistral_LegalDescription",
TermsLabel = "AdvancedPaste_Mistral_TermsLabel",
TermsUri = new Uri("https://mistral.ai/terms-of-service/"),
PrivacyLabel = "AdvancedPaste_Mistral_PrivacyLabel",
PrivacyUri = new Uri("https://mistral.ai/privacy-policy/"),
},
[AIServiceType.ML] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.ML,
DisplayName = "Windows ML",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/WindowsML.svg",
LegalDescription = "AdvancedPaste_LocalModel_LegalDescription",
IsAvailableInUI = false,
IsOnlineService = false,
IsLocalModel = true,
},
[AIServiceType.Ollama] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.Ollama,
DisplayName = "Ollama",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/Ollama.svg",
// Ollama provide online service, but we treat it as local model at first version since it can is known for local model.
IsOnlineService = false,
IsLocalModel = true,
LegalDescription = "AdvancedPaste_LocalModel_LegalDescription",
TermsLabel = "AdvancedPaste_Ollama_TermsLabel",
TermsUri = new Uri("https://ollama.org/terms"),
PrivacyLabel = "AdvancedPaste_Ollama_PrivacyLabel",
PrivacyUri = new Uri("https://ollama.org/privacy"),
},
[AIServiceType.Onnx] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.Onnx,
DisplayName = "ONNX",
LegalDescription = "AdvancedPaste_LocalModel_LegalDescription",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/Onnx.svg",
IsOnlineService = false,
IsAvailableInUI = false,
},
[AIServiceType.OpenAI] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.OpenAI,
DisplayName = "OpenAI",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/OpenAI.light.svg",
IsOnlineService = true,
LegalDescription = "AdvancedPaste_OpenAI_LegalDescription",
TermsLabel = "AdvancedPaste_OpenAI_TermsLabel",
TermsUri = new Uri("https://openai.com/terms"),
PrivacyLabel = "AdvancedPaste_OpenAI_PrivacyLabel",
PrivacyUri = new Uri("https://openai.com/privacy"),
},
[AIServiceType.Unknown] = new AIServiceTypeMetadata
{
ServiceType = AIServiceType.Unknown,
DisplayName = "Unknown",
IconPath = "ms-appx:///Assets/Settings/Icons/Models/OpenAI.light.svg",
IsOnlineService = false,
IsAvailableInUI = false,
},
};
/// <summary>
/// Get metadata for a specific service type.
/// </summary>
public static AIServiceTypeMetadata GetMetadata(AIServiceType serviceType)
{
return MetadataMap.TryGetValue(serviceType, out var metadata)
? metadata
: MetadataMap[AIServiceType.Unknown];
}
/// <summary>
/// Get metadata for a service type from its string representation.
/// </summary>
public static AIServiceTypeMetadata GetMetadata(string serviceType)
{
var type = serviceType.ToAIServiceType();
return GetMetadata(type);
}
/// <summary>
/// Get icon path for a service type.
/// </summary>
public static string GetIconPath(AIServiceType serviceType)
{
return GetMetadata(serviceType).IconPath;
}
/// <summary>
/// Get icon path for a service type from its string representation.
/// </summary>
public static string GetIconPath(string serviceType)
{
return GetMetadata(serviceType).IconPath;
}
/// <summary>
/// Get all service types available in the UI.
/// </summary>
public static IEnumerable<AIServiceTypeMetadata> GetAvailableServiceTypes()
{
return MetadataMap.Values.Where(m => m.IsAvailableInUI);
}
/// <summary>
/// Get all online service types available in the UI.
/// </summary>
public static IEnumerable<AIServiceTypeMetadata> GetOnlineServiceTypes()
{
return GetAvailableServiceTypes().Where(m => m.IsOnlineService);
}
/// <summary>
/// Get all local service types available in the UI.
/// </summary>
public static IEnumerable<AIServiceTypeMetadata> GetLocalServiceTypes()
{
return GetAvailableServiceTypes().Where(m => m.IsLocalModel);
}
}
@@ -0,0 +1,59 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
namespace Microsoft.PowerToys.Settings.UI.Library;
public sealed partial class AdvancedPasteAdditionalAction : Observable, IAdvancedPasteAction
{
private HotkeySettings _shortcut = new();
private bool _isShown;
private bool _hasConflict;
private string _tooltip;
[JsonPropertyName("shortcut")]
public HotkeySettings Shortcut
{
get => _shortcut;
set
{
if (_shortcut != value)
{
// We null-coalesce here rather than outside this branch as we want to raise PropertyChanged when the setter is called
// with null; the ShortcutControl depends on this.
_shortcut = value ?? new();
OnPropertyChanged();
}
}
}
[JsonPropertyName("isShown")]
public bool IsShown
{
get => _isShown;
set => Set(ref _isShown, value);
}
[JsonIgnore]
public bool HasConflict
{
get => _hasConflict;
set => Set(ref _hasConflict, value);
}
[JsonIgnore]
public string Tooltip
{
get => _tooltip;
set => Set(ref _tooltip, value);
}
[JsonIgnore]
public IEnumerable<IAdvancedPasteAction> SubActions => [];
}
@@ -0,0 +1,67 @@
// 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.Linq;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library;
public sealed class AdvancedPasteAdditionalActions
{
private AdvancedPasteAdditionalAction _imageToText = new();
private AdvancedPastePasteAsFileAction _pasteAsFile = new();
private AdvancedPasteTranscodeAction _transcode = new();
public static class PropertyNames
{
public const string ImageToText = "image-to-text";
public const string PasteAsFile = "paste-as-file";
public const string Transcode = "transcode";
}
[JsonPropertyName(PropertyNames.ImageToText)]
public AdvancedPasteAdditionalAction ImageToText
{
get => _imageToText;
init => _imageToText = value ?? new();
}
[JsonPropertyName(PropertyNames.PasteAsFile)]
public AdvancedPastePasteAsFileAction PasteAsFile
{
get => _pasteAsFile;
init => _pasteAsFile = value ?? new();
}
[JsonPropertyName(PropertyNames.Transcode)]
public AdvancedPasteTranscodeAction Transcode
{
get => _transcode;
init => _transcode = value ?? new();
}
public IEnumerable<IAdvancedPasteAction> GetAllActions()
{
return GetAllActionsRecursive([ImageToText, PasteAsFile, Transcode]);
}
/// <summary>
/// Changed to depth-first traversal to ensure ordered output
/// </summary>
/// <param name="actions">The collection of actions to traverse</param>
/// <returns>All actions returned in depth-first order</returns>
private static IEnumerable<IAdvancedPasteAction> GetAllActionsRecursive(IEnumerable<IAdvancedPasteAction> actions)
{
foreach (var action in actions)
{
yield return action;
foreach (var subAction in GetAllActionsRecursive(action.SubActions))
{
yield return subAction;
}
}
}
}
@@ -0,0 +1,164 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts;
namespace Microsoft.PowerToys.Settings.UI.Library;
public sealed class AdvancedPasteCustomAction : Observable, IAdvancedPasteAction, ICloneable
{
private int _id;
private string _name = string.Empty;
private string _description = string.Empty;
private string _prompt = string.Empty;
private HotkeySettings _shortcut = new();
private bool _isShown;
private bool _canMoveUp;
private bool _canMoveDown;
private bool _isValid;
private bool _hasConflict;
private string _tooltip;
[JsonPropertyName("id")]
public int Id
{
get => _id;
set => Set(ref _id, value);
}
[JsonPropertyName("name")]
public string Name
{
get => _name;
set
{
if (Set(ref _name, value))
{
UpdateIsValid();
}
}
}
[JsonPropertyName("description")]
public string Description
{
get => _description;
set => Set(ref _description, value ?? string.Empty);
}
[JsonPropertyName("prompt")]
public string Prompt
{
get => _prompt;
set
{
if (Set(ref _prompt, value))
{
UpdateIsValid();
}
}
}
[JsonPropertyName("shortcut")]
public HotkeySettings Shortcut
{
get => _shortcut;
set
{
if (_shortcut != value)
{
// We null-coalesce here rather than outside this branch as we want to raise PropertyChanged when the setter is called
// with null; the ShortcutControl depends on this.
_shortcut = value ?? new();
OnPropertyChanged();
}
}
}
[JsonPropertyName("isShown")]
public bool IsShown
{
get => _isShown;
set => Set(ref _isShown, value);
}
[JsonIgnore]
public bool CanMoveUp
{
get => _canMoveUp;
set => Set(ref _canMoveUp, value);
}
[JsonIgnore]
public bool CanMoveDown
{
get => _canMoveDown;
set => Set(ref _canMoveDown, value);
}
[JsonIgnore]
public bool IsValid
{
get => _isValid;
private set => Set(ref _isValid, value);
}
[JsonIgnore]
public bool HasConflict
{
get => _hasConflict;
set => Set(ref _hasConflict, value);
}
[JsonIgnore]
public string Tooltip
{
get => _tooltip;
set => Set(ref _tooltip, value);
}
[JsonIgnore]
public IEnumerable<IAdvancedPasteAction> SubActions => [];
public object Clone()
{
AdvancedPasteCustomAction clone = new();
clone.Update(this);
return clone;
}
public void Update(AdvancedPasteCustomAction other)
{
Id = other.Id;
Name = other.Name;
Description = other.Description;
Prompt = other.Prompt;
Shortcut = other.GetShortcutClone();
IsShown = other.IsShown;
CanMoveUp = other.CanMoveUp;
CanMoveDown = other.CanMoveDown;
HasConflict = other.HasConflict;
Tooltip = other.Tooltip;
}
private HotkeySettings GetShortcutClone()
{
object shortcut = null;
if (Shortcut.TryToCmdRepresentable(out string shortcutString))
{
_ = HotkeySettings.TryParseFromCmd(shortcutString, out shortcut);
}
return (shortcut as HotkeySettings) ?? new HotkeySettings();
}
private void UpdateIsValid()
{
IsValid = !string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(Prompt);
}
}
@@ -0,0 +1,26 @@
// 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.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library;
public sealed class AdvancedPasteCustomActions
{
private static readonly JsonSerializerOptions _serializerOptions = new(SettingsSerializationContext.Default.Options)
{
WriteIndented = true,
};
[JsonPropertyName("value")]
public ObservableCollection<AdvancedPasteCustomAction> Value { get; set; } = [];
public AdvancedPasteCustomActions()
{
}
public string ToJsonString() => JsonSerializer.Serialize(this, _serializerOptions);
}
@@ -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;
using System.Collections.ObjectModel;
using System.Linq;
namespace Microsoft.PowerToys.Settings.UI.Library
{
/// <summary>
/// Helper methods for migrating legacy Advanced Paste settings to the updated schema.
/// </summary>
public static class AdvancedPasteMigrationHelper
{
/// <summary>
/// Ensures an OpenAI provider exists in the configuration, creating one if necessary.
/// </summary>
/// <param name="configuration">The configuration instance.</param>
/// <returns>The ensured provider and a flag indicating whether changes were made.</returns>
public static (PasteAIProviderDefinition Provider, bool Updated) EnsureOpenAIProvider(PasteAIConfiguration configuration)
{
if (configuration is null)
{
return (null, false);
}
configuration.Providers ??= new ObservableCollection<PasteAIProviderDefinition>();
const string serviceTypeKey = "OpenAI";
var existingProvider = configuration.Providers.FirstOrDefault(provider => string.Equals(provider.ServiceType, serviceTypeKey, StringComparison.OrdinalIgnoreCase));
bool updated = false;
if (existingProvider is null)
{
existingProvider = CreateProvider(serviceTypeKey);
configuration.Providers.Add(existingProvider);
updated = true;
}
updated |= EnsureActiveProviderIsValid(configuration, existingProvider);
return (existingProvider, updated);
}
/// <summary>
/// Creates a provider with default values for the requested service type.
/// </summary>
private static PasteAIProviderDefinition CreateProvider(string serviceTypeKey)
{
var serviceType = serviceTypeKey.ToAIServiceType();
var metadata = AIServiceTypeRegistry.GetMetadata(serviceType);
var provider = new PasteAIProviderDefinition
{
ServiceType = serviceTypeKey,
ModelName = PasteAIProviderDefaults.GetDefaultModelName(serviceType),
EndpointUrl = string.Empty,
ApiVersion = string.Empty,
DeploymentName = string.Empty,
ModelPath = string.Empty,
SystemPrompt = string.Empty,
ModerationEnabled = serviceType == AIServiceType.OpenAI,
IsLocalModel = metadata.IsLocalModel,
};
return provider;
}
private static bool EnsureActiveProviderIsValid(PasteAIConfiguration configuration, PasteAIProviderDefinition preferredProvider = null)
{
if (configuration?.Providers is null || configuration.Providers.Count == 0)
{
if (!string.IsNullOrWhiteSpace(configuration?.ActiveProviderId))
{
configuration.ActiveProviderId = string.Empty;
return true;
}
return false;
}
bool updated = false;
var activeProvider = configuration.Providers.FirstOrDefault(provider => string.Equals(provider.Id, configuration.ActiveProviderId, StringComparison.OrdinalIgnoreCase));
if (activeProvider is null)
{
activeProvider = preferredProvider ?? configuration.Providers.First();
configuration.ActiveProviderId = activeProvider.Id;
updated = true;
}
foreach (var provider in configuration.Providers)
{
bool shouldBeActive = string.Equals(provider.Id, configuration.ActiveProviderId, StringComparison.OrdinalIgnoreCase);
if (provider.IsActive != shouldBeActive)
{
provider.IsActive = shouldBeActive;
updated = true;
}
}
return updated;
}
}
}
@@ -0,0 +1,56 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
namespace Microsoft.PowerToys.Settings.UI.Library;
public sealed class AdvancedPastePasteAsFileAction : Observable, IAdvancedPasteAction
{
public static class PropertyNames
{
public const string PasteAsTxtFile = "paste-as-txt-file";
public const string PasteAsPngFile = "paste-as-png-file";
public const string PasteAsHtmlFile = "paste-as-html-file";
}
private AdvancedPasteAdditionalAction _pasteAsTxtFile = new();
private AdvancedPasteAdditionalAction _pasteAsPngFile = new();
private AdvancedPasteAdditionalAction _pasteAsHtmlFile = new();
private bool _isShown = true;
[JsonPropertyName("isShown")]
public bool IsShown
{
get => _isShown;
set => Set(ref _isShown, value);
}
[JsonPropertyName(PropertyNames.PasteAsTxtFile)]
public AdvancedPasteAdditionalAction PasteAsTxtFile
{
get => _pasteAsTxtFile;
init => Set(ref _pasteAsTxtFile, value ?? new());
}
[JsonPropertyName(PropertyNames.PasteAsPngFile)]
public AdvancedPasteAdditionalAction PasteAsPngFile
{
get => _pasteAsPngFile;
init => Set(ref _pasteAsPngFile, value ?? new());
}
[JsonPropertyName(PropertyNames.PasteAsHtmlFile)]
public AdvancedPasteAdditionalAction PasteAsHtmlFile
{
get => _pasteAsHtmlFile;
init => Set(ref _pasteAsHtmlFile, value ?? new());
}
[JsonIgnore]
public IEnumerable<IAdvancedPasteAction> SubActions => [PasteAsTxtFile, PasteAsPngFile, PasteAsHtmlFile];
}
@@ -0,0 +1,117 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AdvancedPasteProperties
{
public static readonly HotkeySettings DefaultAdvancedPasteUIShortcut = new HotkeySettings(true, false, false, true, 0x56); // Win+Shift+V
public static readonly HotkeySettings DefaultPasteAsPlainTextShortcut = new HotkeySettings(true, true, true, false, 0x56); // Ctrl+Win+Alt+V
public AdvancedPasteProperties()
{
AdvancedPasteUIShortcut = DefaultAdvancedPasteUIShortcut;
PasteAsPlainTextShortcut = DefaultPasteAsPlainTextShortcut;
PasteAsMarkdownShortcut = new();
PasteAsJsonShortcut = new();
CustomActions = new();
AdditionalActions = new();
IsAIEnabled = false;
ShowCustomPreview = true;
ShowAIPaste = true;
CloseAfterLosingFocus = false;
EnableClipboardPreview = true;
AutoCopySelectionForCustomActionHotkey = false;
PasteAIConfiguration = new();
}
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool IsAIEnabled { get; set; }
private bool? _legacyAdvancedAIEnabled;
[JsonPropertyName("IsAdvancedAIEnabled")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public BoolProperty LegacyAdvancedAIEnabledProperty
{
get => null;
set
{
if (value is not null)
{
LegacyAdvancedAIEnabled = value.Value;
}
}
}
[JsonIgnore]
public bool? LegacyAdvancedAIEnabled
{
get => _legacyAdvancedAIEnabled;
private set => _legacyAdvancedAIEnabled = value;
}
public bool TryConsumeLegacyAdvancedAIEnabled(out bool value)
{
if (_legacyAdvancedAIEnabled is bool flag)
{
value = flag;
_legacyAdvancedAIEnabled = null;
return true;
}
value = default;
return false;
}
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowCustomPreview { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowAIPaste { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool CloseAfterLosingFocus { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool EnableClipboardPreview { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool AutoCopySelectionForCustomActionHotkey { get; set; }
[JsonPropertyName("advanced-paste-ui-hotkey")]
public HotkeySettings AdvancedPasteUIShortcut { get; set; }
[JsonPropertyName("paste-as-plain-hotkey")]
public HotkeySettings PasteAsPlainTextShortcut { get; set; }
[JsonPropertyName("paste-as-markdown-hotkey")]
public HotkeySettings PasteAsMarkdownShortcut { get; set; }
[JsonPropertyName("paste-as-json-hotkey")]
public HotkeySettings PasteAsJsonShortcut { get; set; }
[JsonPropertyName("custom-actions")]
[CmdConfigureIgnoreAttribute]
public AdvancedPasteCustomActions CustomActions { get; set; }
[JsonPropertyName("additional-actions")]
[CmdConfigureIgnoreAttribute]
public AdvancedPasteAdditionalActions AdditionalActions { get; set; }
[JsonPropertyName("paste-ai-configuration")]
[CmdConfigureIgnoreAttribute]
public PasteAIConfiguration PasteAIConfiguration { get; set; }
public override string ToString()
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.AdvancedPasteProperties);
}
}
@@ -0,0 +1,109 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AdvancedPasteSettings : BasePTModuleSettings, ISettingsConfig, IHotkeyConfig
{
public const string ModuleName = "AdvancedPaste";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
[JsonPropertyName("properties")]
public AdvancedPasteProperties Properties { get; set; }
public AdvancedPasteSettings()
{
Properties = new AdvancedPasteProperties();
Version = "1";
Name = ModuleName;
}
public virtual void Save(SettingsUtils settingsUtils)
{
// Save settings to file
var options = _serializerOptions;
ArgumentNullException.ThrowIfNull(settingsUtils);
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
}
public ModuleType GetModuleType() => ModuleType.AdvancedPaste;
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.PasteAsPlainTextShortcut,
value => Properties.PasteAsPlainTextShortcut = value ?? AdvancedPasteProperties.DefaultPasteAsPlainTextShortcut,
"PasteAsPlainText_Shortcut"),
new HotkeyAccessor(
() => Properties.AdvancedPasteUIShortcut,
value => Properties.AdvancedPasteUIShortcut = value ?? AdvancedPasteProperties.DefaultAdvancedPasteUIShortcut,
"AdvancedPasteUI_Shortcut"),
new HotkeyAccessor(
() => Properties.PasteAsMarkdownShortcut,
value => Properties.PasteAsMarkdownShortcut = value ?? new HotkeySettings(),
"PasteAsMarkdown_Shortcut"),
new HotkeyAccessor(
() => Properties.PasteAsJsonShortcut,
value => Properties.PasteAsJsonShortcut = value ?? new HotkeySettings(),
"PasteAsJson_Shortcut"),
};
string[] additionalActionHeaderKeys =
[
"ImageToText",
"PasteAsTxtFile",
"PasteAsPngFile",
"PasteAsHtmlFile",
"TranscodeToMp3",
"TranscodeToMp4",
];
int index = 0;
foreach (var action in Properties.AdditionalActions.GetAllActions())
{
if (action is AdvancedPasteAdditionalAction additionalAction)
{
hotkeyAccessors.Add(new HotkeyAccessor(
() => additionalAction.Shortcut,
value => additionalAction.Shortcut = value ?? new HotkeySettings(),
additionalActionHeaderKeys[index]));
index++;
}
}
// Custom actions do not have localization header, just use the action name.
foreach (var customAction in Properties.CustomActions.Value)
{
hotkeyAccessors.Add(new HotkeyAccessor(
() => customAction.Shortcut,
value => customAction.Shortcut = value ?? new HotkeySettings(),
customAction.Name));
}
return hotkeyAccessors.ToArray();
}
public string GetModuleName()
=> Name;
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
=> false;
}
}
@@ -0,0 +1,47 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
namespace Microsoft.PowerToys.Settings.UI.Library;
public sealed class AdvancedPasteTranscodeAction : Observable, IAdvancedPasteAction
{
public static class PropertyNames
{
public const string TranscodeToMp3 = "transcode-to-mp3";
public const string TranscodeToMp4 = "transcode-to-mp4";
}
private AdvancedPasteAdditionalAction _transcodeToMp3 = new();
private AdvancedPasteAdditionalAction _transcodeToMp4 = new();
private bool _isShown = true;
[JsonPropertyName("isShown")]
public bool IsShown
{
get => _isShown;
set => Set(ref _isShown, value);
}
[JsonPropertyName(PropertyNames.TranscodeToMp3)]
public AdvancedPasteAdditionalAction TranscodeToMp3
{
get => _transcodeToMp3;
init => Set(ref _transcodeToMp3, value ?? new());
}
[JsonPropertyName(PropertyNames.TranscodeToMp4)]
public AdvancedPasteAdditionalAction TranscodeToMp4
{
get => _transcodeToMp4;
init => Set(ref _transcodeToMp4, value ?? new());
}
[JsonIgnore]
public IEnumerable<IAdvancedPasteAction> SubActions => [TranscodeToMp3, TranscodeToMp4];
}
@@ -0,0 +1,87 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
// Needs to be kept in sync with src\modules\alwaysontop\AlwaysOnTop\Settings.h
public class AlwaysOnTopProperties
{
public static readonly HotkeySettings DefaultHotkeyValue = new HotkeySettings(true, true, false, false, 0x54);
public static readonly HotkeySettings DefaultIncreaseOpacityHotkeyValue = new HotkeySettings(true, true, false, false, 0xBB);
public static readonly HotkeySettings DefaultDecreaseOpacityHotkeyValue = new HotkeySettings(true, true, false, false, 0xBD);
public const bool DefaultFrameEnabled = true;
public const bool DefaultShowInSystemMenu = false;
public const int DefaultFrameThickness = 4;
public const string DefaultFrameColor = "#0099cc";
public const bool DefaultFrameAccentColor = true;
public const int DefaultFrameOpacity = 100;
public const bool DefaultSoundEnabled = true;
public const bool DefaultDoNotActivateOnGameMode = true;
public const bool DefaultRoundCornersEnabled = true;
public AlwaysOnTopProperties()
{
Hotkey = new KeyboardKeysProperty(DefaultHotkeyValue);
IncreaseOpacityHotkey = new KeyboardKeysProperty(DefaultIncreaseOpacityHotkeyValue);
DecreaseOpacityHotkey = new KeyboardKeysProperty(DefaultDecreaseOpacityHotkeyValue);
ShowInSystemMenu = new BoolProperty(DefaultShowInSystemMenu);
FrameEnabled = new BoolProperty(DefaultFrameEnabled);
FrameThickness = new IntProperty(DefaultFrameThickness);
FrameColor = new StringProperty(DefaultFrameColor);
FrameAccentColor = new BoolProperty(DefaultFrameAccentColor);
FrameOpacity = new IntProperty(DefaultFrameOpacity);
SoundEnabled = new BoolProperty(DefaultSoundEnabled);
DoNotActivateOnGameMode = new BoolProperty(DefaultDoNotActivateOnGameMode);
RoundCornersEnabled = new BoolProperty(DefaultRoundCornersEnabled);
ExcludedApps = new StringProperty();
}
[JsonPropertyName("hotkey")]
public KeyboardKeysProperty Hotkey { get; set; }
[JsonPropertyName("increase-opacity-hotkey")]
public KeyboardKeysProperty IncreaseOpacityHotkey { get; set; }
[JsonPropertyName("decrease-opacity-hotkey")]
public KeyboardKeysProperty DecreaseOpacityHotkey { get; set; }
[JsonPropertyName("frame-enabled")]
public BoolProperty FrameEnabled { get; set; }
[JsonPropertyName("show-in-system-menu")]
public BoolProperty ShowInSystemMenu { get; set; }
[JsonPropertyName("frame-thickness")]
public IntProperty FrameThickness { get; set; }
[JsonPropertyName("frame-color")]
public StringProperty FrameColor { get; set; }
[JsonPropertyName("frame-opacity")]
public IntProperty FrameOpacity { get; set; }
[JsonPropertyName("frame-accent-color")]
public BoolProperty FrameAccentColor { get; set; }
[JsonPropertyName("sound-enabled")]
public BoolProperty SoundEnabled { get; set; }
[JsonPropertyName("do-not-activate-on-game-mode")]
public BoolProperty DoNotActivateOnGameMode { get; set; }
[JsonPropertyName("excluded-apps")]
public StringProperty ExcludedApps { get; set; }
[JsonPropertyName("round-corners-enabled")]
public BoolProperty RoundCornersEnabled { get; set; }
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}
@@ -0,0 +1,61 @@
// 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.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AlwaysOnTopSettings : BasePTModuleSettings, ISettingsConfig, IHotkeyConfig
{
public const string ModuleName = "AlwaysOnTop";
public const string ModuleVersion = "0.0.1";
public AlwaysOnTopSettings()
{
Name = ModuleName;
Version = ModuleVersion;
Properties = new AlwaysOnTopProperties();
}
[JsonPropertyName("properties")]
public AlwaysOnTopProperties Properties { get; set; }
public string GetModuleName()
{
return Name;
}
public ModuleType GetModuleType() => ModuleType.AlwaysOnTop;
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.Hotkey.Value,
value => Properties.Hotkey.Value = value ?? AlwaysOnTopProperties.DefaultHotkeyValue,
"AlwaysOnTop_ActivationShortcut"),
new HotkeyAccessor(
() => Properties.IncreaseOpacityHotkey.Value,
value => Properties.IncreaseOpacityHotkey.Value = value ?? AlwaysOnTopProperties.DefaultIncreaseOpacityHotkeyValue,
"AlwaysOnTop_IncreaseOpacityShortcut"),
new HotkeyAccessor(
() => Properties.DecreaseOpacityHotkey.Value,
value => Properties.DecreaseOpacityHotkey.Value = value ?? AlwaysOnTopProperties.DefaultDecreaseOpacityHotkeyValue,
"AlwaysOnTop_DecreaseOpacityShortcut"),
};
return hotkeyAccessors.ToArray();
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,57 @@
// 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.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AppSpecificKeysDataModel : KeysDataModel
{
[JsonPropertyName("targetApp")]
public string TargetApp { get; set; }
public new List<string> GetMappedOriginalKeys()
{
return base.GetMappedOriginalKeys();
}
public new List<string> GetMappedOriginalKeysWithSplitChord()
{
return base.GetMappedOriginalKeysWithSplitChord();
}
public List<string> GetMappedOriginalKeys(bool ignoreSecondKeyInChord)
{
return base.GetMappedOriginalKeys(ignoreSecondKeyInChord);
}
public List<string> GetMappedOriginalKeysWithoutChord()
{
return base.GetMappedOriginalKeys(true);
}
public new List<string> GetMappedOriginalKeysOnlyChord()
{
return base.GetMappedOriginalKeysOnlyChord();
}
public new List<string> GetMappedNewRemapKeys(int runProgramMaxLength)
{
return base.GetMappedNewRemapKeys(runProgramMaxLength);
}
public bool Compare(AppSpecificKeysDataModel arg)
{
ArgumentNullException.ThrowIfNull(arg);
// Using Ordinal comparison for internal text
return string.Equals(OriginalKeys, arg.OriginalKeys, StringComparison.Ordinal) &&
string.Equals(NewRemapKeys, arg.NewRemapKeys, StringComparison.Ordinal) &&
string.Equals(NewRemapString, arg.NewRemapString, StringComparison.Ordinal) &&
string.Equals(TargetApp, arg.TargetApp, StringComparison.Ordinal);
}
}
}
@@ -0,0 +1,16 @@
// 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;
namespace Settings.UI.Library.Attributes;
/// <summary>
/// Adding this attribute to a property makes it not configurable from the command line.
/// Typical use cases:
/// - Property represents internal module state.
/// - Property has a type that is unwieldy to type as a command line string.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class CmdConfigureIgnoreAttribute : Attribute;
@@ -0,0 +1,14 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library
{
public enum AwakeMode
{
PASSIVE = 0,
INDEFINITE = 1,
TIMED = 2,
EXPIRABLE = 3,
}
}
@@ -0,0 +1,44 @@
// 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.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AwakeProperties
{
public AwakeProperties()
{
KeepDisplayOn = false;
Mode = AwakeMode.PASSIVE;
IntervalHours = 0;
IntervalMinutes = 1;
ExpirationDateTime = DateTimeOffset.Now;
CustomTrayTimes = [];
}
[JsonPropertyName("keepDisplayOn")]
public bool KeepDisplayOn { get; set; }
[JsonPropertyName("mode")]
public AwakeMode Mode { get; set; }
[JsonPropertyName("intervalHours")]
public uint IntervalHours { get; set; }
[JsonPropertyName("intervalMinutes")]
public uint IntervalMinutes { get; set; }
[JsonPropertyName("expirationDateTime")]
public DateTimeOffset ExpirationDateTime { get; set; }
[JsonPropertyName("customTrayTimes")]
[CmdConfigureIgnore]
public Dictionary<string, uint> CustomTrayTimes { get; set; }
}
}
@@ -0,0 +1,58 @@
// 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.Linq;
using System.Reflection;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class AwakeSettings : BasePTModuleSettings, ISettingsConfig, ICloneable
{
public const string ModuleName = "Awake";
public AwakeSettings()
{
Name = ModuleName;
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Properties = new AwakeProperties();
}
[JsonPropertyName("properties")]
public AwakeProperties Properties { get; set; }
public object Clone()
{
return new AwakeSettings()
{
Name = Name,
Version = Version,
Properties = new AwakeProperties()
{
CustomTrayTimes = Properties.CustomTrayTimes.ToDictionary(entry => entry.Key, entry => entry.Value),
Mode = Properties.Mode,
KeepDisplayOn = Properties.KeepDisplayOn,
IntervalMinutes = Properties.IntervalMinutes,
IntervalHours = Properties.IntervalHours,
// Fix old buggy default value that might be saved in Settings. Some components don't deal well with negative time zones and minimum time offsets.
ExpirationDateTime = Properties.ExpirationDateTime.Year < 2 ? DateTimeOffset.Now : Properties.ExpirationDateTime,
},
};
}
public string GetModuleName()
{
return Name;
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,79 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
/// <summary>
/// Base class for all PowerToys module settings.
/// </summary>
/// <remarks>
/// <para><strong>IMPORTANT for Native AOT compatibility:</strong></para>
/// <para>When creating a new class that inherits from <see cref="BasePTModuleSettings"/>,
/// you MUST register it in <see cref="SettingsSerializationContext"/> by adding a
/// <c>[JsonSerializable(typeof(YourNewSettingsClass))]</c> attribute.</para>
/// <para>Failure to register the type will cause <see cref="ToJsonString"/> to throw
/// <see cref="InvalidOperationException"/> at runtime.</para>
/// <para>See <see cref="SettingsSerializationContext"/> for registration instructions.</para>
/// </remarks>
public abstract class BasePTModuleSettings
{
// Cached JsonSerializerOptions for Native AOT compatibility
private static readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions
{
TypeInfoResolver = SettingsSerializationContext.Default,
};
// Gets or sets name of the powertoy module.
[JsonPropertyName("name")]
public string Name { get; set; }
// Gets or sets the powertoys version.
[JsonPropertyName("version")]
public string Version { get; set; }
/// <summary>
/// Converts the current settings object to a JSON string.
/// </summary>
/// <returns>JSON string representation of this settings object.</returns>
/// <exception cref="InvalidOperationException">
/// Thrown when the runtime type is not registered in <see cref="SettingsSerializationContext"/>.
/// All derived types must be registered with <c>[JsonSerializable(typeof(YourType))]</c> attribute.
/// </exception>
/// <remarks>
/// This method uses Native AOT-compatible JSON serialization. The runtime type must be
/// registered in <see cref="SettingsSerializationContext"/> for serialization to work.
/// </remarks>
public virtual string ToJsonString()
{
// By default JsonSerializer will only serialize the properties in the base class. This can be avoided by passing the object type (more details at https://stackoverflow.com/a/62498888)
var runtimeType = GetType();
// For Native AOT compatibility, get JsonTypeInfo from the TypeInfoResolver
var typeInfo = _jsonSerializerOptions.TypeInfoResolver?.GetTypeInfo(runtimeType, _jsonSerializerOptions);
if (typeInfo == null)
{
throw new InvalidOperationException($"Type {runtimeType.FullName} is not registered in SettingsSerializationContext. Please add it to the [JsonSerializable] attributes.");
}
// Use AOT-friendly serialization
return JsonSerializer.Serialize(this, typeInfo);
}
public override int GetHashCode()
{
return ToJsonString().GetHashCode();
}
public override bool Equals(object obj)
{
var settings = obj as BasePTModuleSettings;
return settings?.ToJsonString() == ToJsonString();
}
}
}
@@ -0,0 +1,49 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public record BoolProperty : ICmdLineRepresentable
{
public BoolProperty()
{
Value = false;
}
public BoolProperty(bool value)
{
Value = value;
}
[JsonPropertyName("value")]
public bool Value { get; set; }
public static bool TryParseFromCmd(string cmd, out object result)
{
result = null;
if (!bool.TryParse(cmd, out bool value))
{
return false;
}
result = new BoolProperty { Value = value };
return true;
}
public override string ToString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.BoolProperty);
}
public bool TryToCmdRepresentable(out string result)
{
result = Value.ToString();
return true;
}
}
}
@@ -0,0 +1,25 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class BoolPropertyJsonConverter : JsonConverter<bool>
{
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var boolProperty = JsonSerializer.Deserialize(ref reader, SettingsSerializationContext.Default.BoolProperty);
return boolProperty.Value;
}
public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options)
{
var boolProperty = new BoolProperty(value);
JsonSerializer.Serialize(writer, boolProperty, SettingsSerializationContext.Default.BoolProperty);
}
}
}
@@ -0,0 +1,43 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class CmdNotFoundSettings : BasePTModuleSettings, ISettingsConfig
{
private static readonly JsonSerializerOptions SerializerOptions = new()
{
WriteIndented = true,
};
public const string ModuleName = "CmdNotFound";
public CmdNotFoundSettings()
{
Version = "1";
Name = ModuleName;
}
public virtual void Save(SettingsUtils settingsUtils)
{
// Save settings to file
ArgumentNullException.ThrowIfNull(settingsUtils);
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, SerializerOptions), ModuleName);
}
public string GetModuleName()
=> Name;
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
=> false;
}
}
@@ -0,0 +1,56 @@
// 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.IO;
using System.Text.Json;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class CmdPalProperties
{
// Default shortcut - Win + Alt + Space
public static readonly HotkeySettings DefaultHotkeyValue = new HotkeySettings(true, false, true, false, 32);
#pragma warning disable SA1401 // Fields should be private
#pragma warning disable CA1051 // Do not declare visible instance fields
public HotkeySettings Hotkey;
#pragma warning restore CA1051 // Do not declare visible instance fields
#pragma warning restore SA1401 // Fields should be private
private string _settingsFilePath;
public CmdPalProperties()
{
var localAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
#if DEBUG
_settingsFilePath = Path.Combine(localAppDataDir, "Packages", "Microsoft.CommandPalette.Dev_8wekyb3d8bbwe", "LocalState", "settings.json");
#else
_settingsFilePath = Path.Combine(localAppDataDir, "Packages", "Microsoft.CommandPalette_8wekyb3d8bbwe", "LocalState", "settings.json");
#endif
InitializeHotkey();
}
public void InitializeHotkey()
{
try
{
string json = File.ReadAllText(_settingsFilePath); // Read JSON file
using JsonDocument doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty(nameof(Hotkey), out JsonElement hotkeyElement))
{
Hotkey = JsonSerializer.Deserialize(hotkeyElement.GetRawText(), SettingsSerializationContext.Default.HotkeySettings);
}
}
catch (Exception)
{
}
Hotkey ??= DefaultHotkeyValue;
}
}
}
@@ -0,0 +1,180 @@
// 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.ComponentModel;
using System.Runtime.CompilerServices;
using ManagedCommon;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ColorFormatModel : INotifyPropertyChanged
{
private string _name;
private string _format;
private bool _isShown;
private bool _canMoveUp = true;
private bool _canMoveDown = true;
private bool _canBeDeleted = true;
private bool _isNew;
private bool _isValid = true;
public ColorFormatModel(string name, string format, bool isShown)
{
Name = name;
Format = format;
IsShown = isShown;
IsNew = false;
}
public ColorFormatModel()
{
Format = "new Color (R = %Re, G = %Gr, B = %Bl)";
IsShown = true;
IsNew = true;
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
public string Format
{
get
{
return _format;
}
set
{
_format = value;
OnPropertyChanged(nameof(Format));
OnPropertyChanged(nameof(Example));
}
}
public bool IsShown
{
get
{
return _isShown;
}
set
{
_isShown = value;
OnPropertyChanged(nameof(IsShown));
}
}
public bool CanMoveUp
{
get
{
return _canMoveUp;
}
set
{
if (value != _canMoveUp)
{
_canMoveUp = value;
OnPropertyChanged(nameof(CanMoveUp));
}
}
}
public bool CanMoveDown
{
get
{
return _canMoveDown;
}
set
{
if (value != _canMoveDown)
{
_canMoveDown = value;
OnPropertyChanged(nameof(CanMoveDown));
}
}
}
public bool CanBeDeleted
{
get
{
return _canBeDeleted;
}
set
{
if (value != _canBeDeleted)
{
_canBeDeleted = value;
OnPropertyChanged(nameof(CanBeDeleted));
}
}
}
public bool IsNew
{
get
{
return _isNew;
}
set
{
_isNew = value;
OnPropertyChanged(nameof(IsNew));
}
}
public bool IsValid
{
get
{
return _isValid;
}
set
{
_isValid = value;
OnPropertyChanged(nameof(IsValid));
}
}
public string Example
{
get
{
// get string representation in 2 steps. First replace all color specific number values then in 2nd step replace color name with localisation
return Helpers.ColorNameHelper.ReplaceName(ColorFormatHelper.GetStringRepresentation(null, _format), null);
}
set
{
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
@@ -0,0 +1,92 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ColorPickerProperties
{
[CmdConfigureIgnore]
public HotkeySettings DefaultActivationShortcut => new HotkeySettings(true, false, false, true, 0x43);
public ColorPickerProperties()
{
ActivationShortcut = DefaultActivationShortcut;
ChangeCursor = false;
ColorHistoryLimit = 20;
VisibleColorFormats = new Dictionary<string, KeyValuePair<bool, string>>();
VisibleColorFormats.Add("HEX", new KeyValuePair<bool, string>(true, ColorFormatHelper.GetDefaultFormat("HEX")));
VisibleColorFormats.Add("RGB", new KeyValuePair<bool, string>(true, ColorFormatHelper.GetDefaultFormat("RGB")));
VisibleColorFormats.Add("HSL", new KeyValuePair<bool, string>(true, ColorFormatHelper.GetDefaultFormat("HSL")));
VisibleColorFormats.Add("HSV", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HSV")));
VisibleColorFormats.Add("CMYK", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("CMYK")));
VisibleColorFormats.Add("HSB", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HSB")));
VisibleColorFormats.Add("HSI", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HSI")));
VisibleColorFormats.Add("HWB", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HWB")));
VisibleColorFormats.Add("NCol", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("NCol")));
VisibleColorFormats.Add("CIEXYZ", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("CIEXYZ")));
VisibleColorFormats.Add("CIELAB", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("CIELAB")));
VisibleColorFormats.Add("Oklab", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("Oklab")));
VisibleColorFormats.Add("Oklch", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("Oklch")));
VisibleColorFormats.Add("VEC4", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("VEC4")));
VisibleColorFormats.Add("Decimal", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("Decimal")));
VisibleColorFormats.Add("HEX Int", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HEX Int")));
ShowColorName = false;
ActivationAction = ColorPickerActivationAction.OpenColorPicker;
PrimaryClickAction = ColorPickerClickAction.PickColorThenEditor;
MiddleClickAction = ColorPickerClickAction.PickColorAndClose;
SecondaryClickAction = ColorPickerClickAction.Close;
CopiedColorRepresentation = "HEX";
}
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("changecursor")]
[JsonConverter(typeof(BoolPropertyJsonConverter))]
[CmdConfigureIgnoreAttribute]
public bool ChangeCursor { get; set; }
[JsonPropertyName("copiedcolorrepresentation")]
public string CopiedColorRepresentation { get; set; }
[JsonPropertyName("activationaction")]
public ColorPickerActivationAction ActivationAction { get; set; }
[JsonPropertyName("primaryclickaction")]
public ColorPickerClickAction PrimaryClickAction { get; set; }
[JsonPropertyName("middleclickaction")]
public ColorPickerClickAction MiddleClickAction { get; set; }
[JsonPropertyName("secondaryclickaction")]
public ColorPickerClickAction SecondaryClickAction { get; set; }
// Property ColorHistory is not used, the color history is saved separately in the colorHistory.json file
[JsonPropertyName("colorhistory")]
[CmdConfigureIgnoreAttribute]
public List<string> ColorHistory { get; set; }
[JsonPropertyName("colorhistorylimit")]
[CmdConfigureIgnoreAttribute]
public int ColorHistoryLimit { get; set; }
[JsonPropertyName("visiblecolorformats")]
[CmdConfigureIgnoreAttribute]
public Dictionary<string, KeyValuePair<bool, string>> VisibleColorFormats { get; set; }
[JsonPropertyName("showcolorname")]
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowColorName { get; set; }
public override string ToString()
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerProperties);
}
}
@@ -0,0 +1,59 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ColorPickerPropertiesVersion1
{
public HotkeySettings DefaultActivationShortcut => new HotkeySettings(true, false, false, true, 0x43);
public ColorPickerPropertiesVersion1()
{
ActivationShortcut = DefaultActivationShortcut;
ChangeCursor = false;
ColorHistory = new List<string>();
ColorHistoryLimit = 20;
VisibleColorFormats = new Dictionary<string, bool>();
VisibleColorFormats.Add("HEX", true);
VisibleColorFormats.Add("RGB", true);
VisibleColorFormats.Add("HSL", true);
ShowColorName = false;
ActivationAction = ColorPickerActivationAction.OpenColorPicker;
}
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("changecursor")]
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ChangeCursor { get; set; }
[JsonPropertyName("copiedcolorrepresentation")]
public ColorRepresentationType CopiedColorRepresentation { get; set; }
[JsonPropertyName("activationaction")]
public ColorPickerActivationAction ActivationAction { get; set; }
[JsonPropertyName("colorhistory")]
public List<string> ColorHistory { get; set; }
[JsonPropertyName("colorhistorylimit")]
public int ColorHistoryLimit { get; set; }
[JsonPropertyName("visiblecolorformats")]
public Dictionary<string, bool> VisibleColorFormats { get; set; }
[JsonPropertyName("showcolorname")]
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowColorName { get; set; }
public override string ToString()
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerPropertiesVersion1);
}
}
@@ -0,0 +1,102 @@
// 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.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ColorPickerSettings : BasePTModuleSettings, ISettingsConfig, IHotkeyConfig
{
public const string ModuleName = "ColorPicker";
[JsonPropertyName("properties")]
public ColorPickerProperties Properties { get; set; }
public ColorPickerSettings()
{
Properties = new ColorPickerProperties();
Version = "2.1";
Name = ModuleName;
}
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
public virtual void Save(SettingsUtils settingsUtils)
{
// Save settings to file
var options = _serializerOptions;
ArgumentNullException.ThrowIfNull(settingsUtils);
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
}
public string GetModuleName()
=> Name;
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
// Upgrading V1 to V2 doesn't set the version to 2.0, therefore V2 settings still report Version == 1.0
if (Version == "1.0")
{
if (!Enum.IsDefined(Properties.ActivationAction))
{
Properties.ActivationAction = ColorPickerActivationAction.OpenColorPicker;
}
Version = "2.1";
return true;
}
return false;
}
public ModuleType GetModuleType() => ModuleType.ColorPicker;
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.ActivationShortcut,
value => Properties.ActivationShortcut = value ?? Properties.DefaultActivationShortcut,
"Activation_Shortcut"),
};
return hotkeyAccessors.ToArray();
}
public static object UpgradeSettings(object oldSettingsObject)
{
ColorPickerSettingsVersion1 oldSettings = (ColorPickerSettingsVersion1)oldSettingsObject;
ColorPickerSettings newSettings = new ColorPickerSettings();
newSettings.Properties.ActivationShortcut = oldSettings.Properties.ActivationShortcut;
newSettings.Properties.ChangeCursor = oldSettings.Properties.ChangeCursor;
newSettings.Properties.ActivationAction = oldSettings.Properties.ActivationAction;
newSettings.Properties.ColorHistoryLimit = oldSettings.Properties.ColorHistoryLimit;
newSettings.Properties.ShowColorName = oldSettings.Properties.ShowColorName;
newSettings.Properties.ActivationShortcut = oldSettings.Properties.ActivationShortcut;
newSettings.Properties.VisibleColorFormats = new Dictionary<string, KeyValuePair<bool, string>>();
foreach (KeyValuePair<string, bool> oldValue in oldSettings.Properties.VisibleColorFormats)
{
newSettings.Properties.VisibleColorFormats.Add(oldValue.Key, new KeyValuePair<bool, string>(oldValue.Value, ColorFormatHelper.GetDefaultFormat(oldValue.Key)));
}
newSettings.Properties.CopiedColorRepresentation = newSettings.Properties.VisibleColorFormats.ElementAt((int)oldSettings.Properties.CopiedColorRepresentation).Key;
return newSettings;
}
}
}
@@ -0,0 +1,48 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ColorPickerSettingsVersion1 : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "ColorPicker";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
[JsonPropertyName("properties")]
public ColorPickerPropertiesVersion1 Properties { get; set; }
public ColorPickerSettingsVersion1()
{
Properties = new ColorPickerPropertiesVersion1();
Version = "1";
Name = ModuleName;
}
public virtual void Save(SettingsUtils settingsUtils)
{
// Save settings to file
var options = _serializerOptions;
ArgumentNullException.ThrowIfNull(settingsUtils);
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
}
public string GetModuleName()
=> Name;
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
=> false;
}
}
@@ -0,0 +1,22 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library
{
public static class ConfigDefaults
{
// Fancy Zones Default Colors
public static readonly string DefaultFancyZonesZoneHighlightColor = "#0078D7";
public static readonly string DefaultFancyZonesInActiveColor = "#F5FCFF";
public static readonly string DefaultFancyzonesBorderColor = "#FFFFFF";
public static readonly string DefaultFancyzonesNumberColor = "#000000";
// Fancy Zones Default Flags.
public static readonly bool DefaultFancyzonesShiftDrag = true;
public static readonly bool DefaultUseCursorposEditorStartupscreen = true;
public static readonly bool DefaultFancyzonesQuickLayoutSwitch = true;
public static readonly bool DefaultFancyzonesFlashZonesOnQuickSwitch = true;
public static readonly bool DefaultFancyzonesDisplayOrWorkAreaChangeMoveWindows = true;
}
}
@@ -0,0 +1,32 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class CropAndLockProperties
{
public static readonly HotkeySettings DefaultReparentHotkeyValue = new HotkeySettings(true, true, false, true, 0x52); // Ctrl+Win+Shift+R
public static readonly HotkeySettings DefaultThumbnailHotkeyValue = new HotkeySettings(true, true, false, true, 0x54); // Ctrl+Win+Shift+T
public static readonly HotkeySettings DefaultScreenshotHotkeyValue = new HotkeySettings(true, true, false, true, 0x53); // Ctrl+Win+Shift+S
public CropAndLockProperties()
{
ReparentHotkey = new KeyboardKeysProperty(DefaultReparentHotkeyValue);
ThumbnailHotkey = new KeyboardKeysProperty(DefaultThumbnailHotkeyValue);
ScreenshotHotkey = new KeyboardKeysProperty(DefaultScreenshotHotkeyValue);
}
[JsonPropertyName("reparent-hotkey")]
public KeyboardKeysProperty ReparentHotkey { get; set; }
[JsonPropertyName("thumbnail-hotkey")]
public KeyboardKeysProperty ThumbnailHotkey { get; set; }
[JsonPropertyName("screenshot-hotkey")]
public KeyboardKeysProperty ScreenshotHotkey { get; set; }
}
}
@@ -0,0 +1,61 @@
// 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.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class CropAndLockSettings : BasePTModuleSettings, ISettingsConfig, IHotkeyConfig
{
public const string ModuleName = "CropAndLock";
public const string ModuleVersion = "0.0.1";
public CropAndLockSettings()
{
Name = ModuleName;
Version = ModuleVersion;
Properties = new CropAndLockProperties();
}
[JsonPropertyName("properties")]
public CropAndLockProperties Properties { get; set; }
public string GetModuleName()
{
return Name;
}
public ModuleType GetModuleType() => ModuleType.CropAndLock;
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.ReparentHotkey.Value,
value => Properties.ReparentHotkey.Value = value ?? CropAndLockProperties.DefaultReparentHotkeyValue,
"CropAndLock_ReparentActivation_Shortcut"),
new HotkeyAccessor(
() => Properties.ThumbnailHotkey.Value,
value => Properties.ThumbnailHotkey.Value = value ?? CropAndLockProperties.DefaultThumbnailHotkeyValue,
"CropAndLock_ThumbnailActivation_Shortcut"),
new HotkeyAccessor(
() => Properties.ScreenshotHotkey.Value,
value => Properties.ScreenshotHotkey.Value = value ?? CropAndLockProperties.DefaultScreenshotHotkeyValue,
"CropAndLock_ScreenshotActivation_Shortcut"),
};
return hotkeyAccessors.ToArray();
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,44 @@
// 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.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class CursorWrapProperties
{
[CmdConfigureIgnore]
public HotkeySettings DefaultActivationShortcut => new HotkeySettings(true, false, true, false, 0x55); // Win + Alt + U
[JsonPropertyName("activation_shortcut")]
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("auto_activate")]
public BoolProperty AutoActivate { get; set; }
[JsonPropertyName("disable_wrap_during_drag")]
public BoolProperty DisableWrapDuringDrag { get; set; }
[JsonPropertyName("wrap_mode")]
public IntProperty WrapMode { get; set; }
[JsonPropertyName("activation_mode")]
public IntProperty ActivationMode { get; set; }
[JsonPropertyName("disable_cursor_wrap_on_single_monitor")]
public BoolProperty DisableCursorWrapOnSingleMonitor { get; set; }
public CursorWrapProperties()
{
ActivationShortcut = DefaultActivationShortcut;
AutoActivate = new BoolProperty(false);
DisableWrapDuringDrag = new BoolProperty(true);
WrapMode = new IntProperty(0); // 0=Both (default), 1=VerticalOnly, 2=HorizontalOnly
ActivationMode = new IntProperty(0); // 0=Always (default), 1=HoldingCtrl, 2=HoldingShift
DisableCursorWrapOnSingleMonitor = new BoolProperty(false);
}
}
}
@@ -0,0 +1,76 @@
// 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.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class CursorWrapSettings : BasePTModuleSettings, ISettingsConfig, IHotkeyConfig
{
public const string ModuleName = "CursorWrap";
[JsonPropertyName("properties")]
public CursorWrapProperties Properties { get; set; }
public CursorWrapSettings()
{
Name = ModuleName;
Properties = new CursorWrapProperties();
Version = "1.0";
}
public string GetModuleName()
{
return Name;
}
public ModuleType GetModuleType() => ModuleType.CursorWrap;
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.ActivationShortcut,
value => Properties.ActivationShortcut = value ?? Properties.DefaultActivationShortcut,
"MouseUtils_CursorWrap_ActivationShortcut"),
};
return hotkeyAccessors.ToArray();
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
bool settingsUpgraded = false;
// Add WrapMode property if it doesn't exist (for users upgrading from older versions)
if (Properties.WrapMode == null)
{
Properties.WrapMode = new IntProperty(0); // Default to Both
settingsUpgraded = true;
}
// Add ActivationMode property if it doesn't exist (for users upgrading from older versions)
if (Properties.ActivationMode == null)
{
Properties.ActivationMode = new IntProperty(0); // Default to Always (0=Always, 1=HoldingCtrl, 2=HoldingShift)
settingsUpgraded = true;
}
// Add DisableCursorWrapOnSingleMonitor property if it doesn't exist (for users upgrading from older versions)
if (Properties.DisableCursorWrapOnSingleMonitor == null)
{
Properties.DisableCursorWrapOnSingleMonitor = new BoolProperty(false); // Default to false
settingsUpgraded = true;
}
return settingsUpgraded;
}
}
}
@@ -0,0 +1,17 @@
// 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.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library.CustomAction
{
public class CustomActionDataModel
{
[JsonPropertyName("action_name")]
public string Name { get; set; }
[JsonPropertyName("value")]
public string Value { get; set; }
}
}
@@ -0,0 +1,24 @@
// 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.Text.Json;
namespace Microsoft.PowerToys.Settings.UI.Library.CustomAction
{
public class CustomNamePolicy : JsonNamingPolicy
{
private Func<string, string> convertDelegate;
public CustomNamePolicy(Func<string, string> convertDelegate)
{
this.convertDelegate = convertDelegate;
}
public override string ConvertName(string name)
{
return convertDelegate(name);
}
}
}
@@ -0,0 +1,11 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.CustomAction
{
public class ModuleCustomAction
{
public CustomActionDataModel ModuleAction { get; set; }
}
}
@@ -0,0 +1,43 @@
// 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.Concurrent;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library.CustomAction
{
public class SendCustomAction
{
private static readonly ConcurrentDictionary<string, JsonSerializerOptions> OptionsCache = new ConcurrentDictionary<string, JsonSerializerOptions>();
private readonly string moduleName;
public SendCustomAction(string moduleName)
{
this.moduleName = moduleName;
}
[JsonPropertyName("action")]
public ModuleCustomAction Action { get; set; }
public string ToJsonString()
{
var jsonSerializerOptions = OptionsCache.GetOrAdd(moduleName, CreateOptionsForModuleName);
return JsonSerializer.Serialize(this, jsonSerializerOptions);
}
private JsonSerializerOptions CreateOptionsForModuleName(string moduleName)
{
return new JsonSerializerOptions
{
PropertyNamingPolicy = new CustomNamePolicy((propertyName) =>
{
// Using Ordinal as this is an internal property name
return propertyName.Equals("ModuleAction", System.StringComparison.Ordinal) ? moduleName : propertyName;
}),
};
}
}
}
@@ -0,0 +1,33 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
// Represents the configuration property of the settings that store Double type.
public class DoubleProperty
{
public DoubleProperty()
{
Value = 0.0;
}
public DoubleProperty(double value)
{
Value = value;
}
// Gets or sets the double value of the settings configuration.
[JsonPropertyName("value")]
public double Value { get; set; }
// Returns a JSON version of the class settings configuration class.
public override string ToString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.DoubleProperty);
}
}
}
@@ -0,0 +1,608 @@
// 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.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.Telemetry;
using Microsoft.PowerToys.Telemetry;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class EnabledModules
{
private Action notifyEnabledChangedAction;
// Default values for enabled modules should match their expected "enabled by default" values.
// Otherwise, a run of DSC on clean settings will not match the expected default result.
public EnabledModules()
{
}
private bool fancyZones = true;
[JsonPropertyName("FancyZones")]
public bool FancyZones
{
get => fancyZones;
set
{
if (fancyZones != value)
{
LogTelemetryEvent(value);
fancyZones = value;
NotifyChange();
}
}
}
private bool imageResizer = true;
[JsonPropertyName("Image Resizer")]
public bool ImageResizer
{
get => imageResizer;
set
{
if (imageResizer != value)
{
LogTelemetryEvent(value);
imageResizer = value;
}
}
}
private bool fileExplorerPreview = true;
[JsonPropertyName("File Explorer Preview")]
public bool PowerPreview
{
get => fileExplorerPreview;
set
{
if (fileExplorerPreview != value)
{
LogTelemetryEvent(value);
fileExplorerPreview = value;
}
}
}
private bool shortcutGuide; // defaulting to off
[JsonPropertyName("Shortcut Guide")]
public bool ShortcutGuide
{
get => shortcutGuide;
set
{
if (shortcutGuide != value)
{
LogTelemetryEvent(value);
shortcutGuide = value;
NotifyChange();
}
}
}
private bool powerRename = true;
public bool PowerRename
{
get => powerRename;
set
{
if (powerRename != value)
{
LogTelemetryEvent(value);
powerRename = value;
}
}
}
private bool keyboardManager; // defaulting to off
[JsonPropertyName("Keyboard Manager")]
public bool KeyboardManager
{
get => keyboardManager;
set
{
if (keyboardManager != value)
{
LogTelemetryEvent(value);
keyboardManager = value;
}
}
}
private bool powerLauncher; // defaulting to off
[JsonPropertyName("PowerToys Run")]
public bool PowerLauncher
{
get => powerLauncher;
set
{
if (powerLauncher != value)
{
LogTelemetryEvent(value);
powerLauncher = value;
NotifyChange();
}
}
}
private bool colorPicker = true;
[JsonPropertyName("ColorPicker")]
public bool ColorPicker
{
get => colorPicker;
set
{
if (colorPicker != value)
{
LogTelemetryEvent(value);
colorPicker = value;
NotifyChange();
}
}
}
private bool cropAndLock; // defaulting to off
[JsonPropertyName("CropAndLock")]
public bool CropAndLock
{
get => cropAndLock;
set
{
if (cropAndLock != value)
{
LogTelemetryEvent(value);
cropAndLock = value;
NotifyChange();
}
}
}
private bool awake = true;
[JsonPropertyName("Awake")]
public bool Awake
{
get => awake;
set
{
if (awake != value)
{
LogTelemetryEvent(value);
awake = value;
}
}
}
private bool mouseWithoutBorders; // defaulting to off
[JsonPropertyName("MouseWithoutBorders")]
public bool MouseWithoutBorders
{
get => mouseWithoutBorders;
set
{
if (mouseWithoutBorders != value)
{
LogTelemetryEvent(value);
mouseWithoutBorders = value;
}
}
}
private bool findMyMouse = true;
[JsonPropertyName("FindMyMouse")]
public bool FindMyMouse
{
get => findMyMouse;
set
{
if (findMyMouse != value)
{
LogTelemetryEvent(value);
findMyMouse = value;
}
}
}
private bool mouseHighlighter = true;
[JsonPropertyName("MouseHighlighter")]
public bool MouseHighlighter
{
get => mouseHighlighter;
set
{
if (mouseHighlighter != value)
{
LogTelemetryEvent(value);
mouseHighlighter = value;
}
}
}
private bool mouseJump; // defaulting to off
[JsonPropertyName("MouseJump")]
public bool MouseJump
{
get => mouseJump;
set
{
if (mouseJump != value)
{
LogTelemetryEvent(value);
mouseJump = value;
}
}
}
private bool alwaysOnTop = true;
[JsonPropertyName("AlwaysOnTop")]
public bool AlwaysOnTop
{
get => alwaysOnTop;
set
{
if (alwaysOnTop != value)
{
LogTelemetryEvent(value);
alwaysOnTop = value;
}
}
}
private bool mousePointerCrosshairs; // defaulting to off
[JsonPropertyName("MousePointerCrosshairs")]
public bool MousePointerCrosshairs
{
get => mousePointerCrosshairs;
set
{
if (mousePointerCrosshairs != value)
{
LogTelemetryEvent(value);
mousePointerCrosshairs = value;
}
}
}
private bool powerAccent; // defaulting to off
[JsonPropertyName("QuickAccent")]
public bool PowerAccent
{
get => powerAccent;
set
{
if (powerAccent != value)
{
LogTelemetryEvent(value);
powerAccent = value;
}
}
}
private bool powerOCR; // defaulting to off
[JsonPropertyName("TextExtractor")]
public bool PowerOcr
{
get => powerOCR;
set
{
if (powerOCR != value)
{
LogTelemetryEvent(value);
powerOCR = value;
NotifyChange();
}
}
}
private bool advancedPaste; // defaulting to off
[JsonPropertyName("AdvancedPaste")]
public bool AdvancedPaste
{
get => advancedPaste;
set
{
if (advancedPaste != value)
{
LogTelemetryEvent(value);
advancedPaste = value;
NotifyChange();
}
}
}
private bool measureTool = true;
[JsonPropertyName("Measure Tool")]
public bool MeasureTool
{
get => measureTool;
set
{
if (measureTool != value)
{
LogTelemetryEvent(value);
measureTool = value;
NotifyChange();
}
}
}
private bool hosts; // defaulting to off
[JsonPropertyName("Hosts")]
public bool Hosts
{
get => hosts;
set
{
if (hosts != value)
{
LogTelemetryEvent(value);
hosts = value;
NotifyChange();
}
}
}
private bool fileLocksmith = true;
[JsonPropertyName("File Locksmith")]
public bool FileLocksmith
{
get => fileLocksmith;
set
{
if (fileLocksmith != value)
{
LogTelemetryEvent(value);
fileLocksmith = value;
}
}
}
private bool peek = true;
[JsonPropertyName("Peek")]
public bool Peek
{
get => peek;
set
{
if (peek != value)
{
LogTelemetryEvent(value);
peek = value;
}
}
}
private bool registryPreview; // defaulting to off
[JsonPropertyName("RegistryPreview")]
public bool RegistryPreview
{
get => registryPreview;
set
{
if (registryPreview != value)
{
LogTelemetryEvent(value);
registryPreview = value;
}
}
}
private bool cmdNotFound = true;
[JsonPropertyName("CmdNotFound")]
public bool CmdNotFound
{
get => cmdNotFound;
set
{
if (cmdNotFound != value)
{
LogTelemetryEvent(value);
cmdNotFound = value;
NotifyChange();
}
}
}
private bool environmentVariables; // defaulting to off
[JsonPropertyName("EnvironmentVariables")]
public bool EnvironmentVariables
{
get => environmentVariables;
set
{
if (environmentVariables != value)
{
LogTelemetryEvent(value);
environmentVariables = value;
}
}
}
private bool newPlus;
[JsonPropertyName("NewPlus")] // This key must match newplus::constants::non_localizable
public bool NewPlus
{
get => newPlus;
set
{
if (newPlus != value)
{
LogTelemetryEvent(value);
newPlus = value;
}
}
}
private bool workspaces; // defaulting to off
[JsonPropertyName("Workspaces")]
public bool Workspaces
{
get => workspaces;
set
{
if (workspaces != value)
{
LogTelemetryEvent(value);
workspaces = value;
NotifyChange();
}
}
}
private bool cmdPal = true;
[JsonPropertyName("CmdPal")]
public bool CmdPal
{
get => cmdPal;
set
{
if (cmdPal != value)
{
LogTelemetryEvent(value);
cmdPal = value;
}
}
}
private bool zoomIt;
[JsonPropertyName("ZoomIt")]
public bool ZoomIt
{
get => zoomIt;
set
{
if (zoomIt != value)
{
LogTelemetryEvent(value);
zoomIt = value;
NotifyChange();
}
}
}
private bool cursorWrap; // defaulting to off
[JsonPropertyName("CursorWrap")]
public bool CursorWrap
{
get => cursorWrap;
set
{
if (cursorWrap != value)
{
LogTelemetryEvent(value);
cursorWrap = value;
}
}
}
private bool lightSwitch;
[JsonPropertyName("LightSwitch")]
public bool LightSwitch
{
get => lightSwitch;
set
{
if (lightSwitch != value)
{
LogTelemetryEvent(value);
lightSwitch = value;
NotifyChange();
}
}
}
private bool powerDisplay;
[JsonPropertyName("PowerDisplay")]
public bool PowerDisplay
{
get => powerDisplay;
set
{
if (powerDisplay != value)
{
LogTelemetryEvent(value);
powerDisplay = value;
NotifyChange();
}
}
}
private bool grabAndMove;
[JsonPropertyName("GrabAndMove")]
public bool GrabAndMove
{
get => grabAndMove;
set
{
if (grabAndMove != value)
{
LogTelemetryEvent(value);
grabAndMove = value;
NotifyChange();
}
}
}
private void NotifyChange()
{
notifyEnabledChangedAction?.Invoke();
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
private static void LogTelemetryEvent(bool value, [CallerMemberName] string moduleName = null)
{
var dataEvent = new SettingsEnabledEvent()
{
Value = value,
Name = moduleName,
};
PowerToysTelemetry.Log.WriteEvent(dataEvent);
}
internal void AddEnabledModuleChangeNotification(Action callBack)
{
notifyEnabledChangedAction = callBack;
}
}
}
@@ -0,0 +1,15 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
{
public enum ColorPickerActivationAction
{
// Activation shortcut opens editor
OpenEditor,
// Activation shortcut opens color picker and after picking a color is copied into clipboard and editor optionally opens depending on which mouse button was pressed
OpenColorPicker,
}
}
@@ -0,0 +1,18 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
{
public enum ColorPickerClickAction
{
// Clicking copies the picked color and opens the editor
PickColorThenEditor,
// Clicking only copies the picked color and then exits color picker
PickColorAndClose,
// Clicking exits color picker, without copying anything
Close,
}
}
@@ -0,0 +1,99 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
{
// NOTE: don't change the order (numbers) of the enumeration entries
/// <summary>
/// The type of the color representation
/// </summary>
public enum ColorRepresentationType
{
/// <summary>
/// Color presentation as hexadecimal color value without the alpha-value (e.g. #0055FF)
/// </summary>
HEX = 0,
/// <summary>
/// Color presentation as RGB color value (red[0..255], green[0..255], blue[0..255])
/// </summary>
RGB = 1,
/// <summary>
/// Color presentation as CMYK color value (cyan[0%..100%], magenta[0%..100%], yellow[0%..100%], black key[0%..100%])
/// </summary>
CMYK = 2,
/// <summary>
/// Color presentation as HSL color value (hue[0°..360°], saturation[0..100%], lightness[0%..100%])
/// </summary>
HSL = 3,
/// <summary>
/// Color presentation as HSV color value (hue[0°..360°], saturation[0%..100%], value[0%..100%])
/// </summary>
HSV = 4,
/// <summary>
/// Color presentation as HSB color value (hue[0°..360°], saturation[0%..100%], brightness[0%..100%])
/// </summary>
HSB = 5,
/// <summary>
/// Color presentation as HSI color value (hue[0°..360°], saturation[0%..100%], intensity[0%..100%])
/// </summary>
HSI = 6,
/// <summary>
/// Color presentation as HWB color value (hue[0°..360°], whiteness[0%..100%], blackness[0%..100%])
/// </summary>
HWB = 7,
/// <summary>
/// Color presentation as natural color (hue, whiteness[0%..100%], blackness[0%..100%])
/// </summary>
NCol = 8,
/// <summary>
/// Color presentation as CIELAB color space, also referred to as CIELAB(L[0..100], A[-128..127], B[-128..127])
/// </summary>
CIELAB = 9,
/// <summary>
/// Color presentation as CIEXYZ color space (X[0..95], Y[0..100], Z[0..109]
/// </summary>
CIEXYZ = 10,
/// <summary>
/// Color presentation as RGB float (red[0..1], green[0..1], blue[0..1])
/// </summary>
VEC4 = 11,
/// <summary>
/// Color presentation as integer decimal value 0-16777215
/// </summary>
DecimalValue = 12,
/// <summary>
/// Color presentation as an 8-digit hexadecimal integer (0xFFFFFFFF)
/// </summary>
HexInteger = 13,
/// <summary>
/// Color representation as CIELCh color space (L[0..100], C[0..230], h[0°..360°])
/// </summary>
CIELCh = 14,
/// <summary>
/// Color representation as Oklab color space (L[0..1], a[-0.5..0.5], b[-0.5..0.5])
/// </summary>
Oklab = 15,
/// <summary>
/// Color representation as Oklch color space (L[0..1], C[0..0.5], h[0°..360°])
/// </summary>
Oklch = 16,
}
}
@@ -0,0 +1,12 @@
// 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.
namespace Settings.UI.Library.Enumerations
{
public enum HostsAdditionalLinesPosition
{
Top = 0,
Bottom = 1,
}
}
@@ -0,0 +1,13 @@
// 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.
namespace Settings.UI.Library.Enumerations
{
public enum HostsDeleteBackupMode
{
Never = 0,
Count = 1,
Age = 2,
}
}
@@ -0,0 +1,12 @@
// 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.
namespace Settings.UI.Library.Enumerations
{
public enum HostsEncoding
{
Utf8 = 0,
Utf8Bom = 1,
}
}
@@ -0,0 +1,15 @@
// 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.
namespace Settings.UI.Library.Enumerations
{
public enum MeasureToolMeasureStyle
{
None,
Bounds,
Spacing,
HorizontalSpacing,
VerticalSpacing,
}
}
@@ -0,0 +1,14 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
{
public enum PowerAccentActivationKey
{
LeftRightArrow,
Space,
Both,
PressAndHold,
}
}
@@ -0,0 +1,13 @@
// 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.
namespace Settings.UI.Library.Enumerations
{
public enum SvgPreviewCheckeredShade
{
Light,
Medium,
Dark,
}
}
@@ -0,0 +1,13 @@
// 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.
namespace Settings.UI.Library.Enumerations
{
public enum SvgPreviewColorMode
{
Default,
SolidColor,
Checkered,
}
}
@@ -0,0 +1,21 @@
// 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.Text.Json.Serialization;
using Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class EnvironmentVariablesProperties
{
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool LaunchAdministrator { get; set; }
public EnvironmentVariablesProperties()
{
LaunchAdministrator = true;
}
}
}
@@ -0,0 +1,46 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class EnvironmentVariablesSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "EnvironmentVariables";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
[JsonPropertyName("properties")]
public EnvironmentVariablesProperties Properties { get; set; }
public EnvironmentVariablesSettings()
{
Properties = new EnvironmentVariablesProperties();
Version = "1.0";
Name = ModuleName;
}
public virtual void Save(SettingsUtils settingsUtils)
{
// Save settings to file
var options = _serializerOptions;
ArgumentNullException.ThrowIfNull(settingsUtils);
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
}
public string GetModuleName() => Name;
public bool UpgradeSettingsConfiguration() => false;
}
}
@@ -0,0 +1,166 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FZConfigProperties
{
// in reality, this file needs to be kept in sync currently with src\modules\fancyzones\lib\Settings.h
public const int VkOem3 = 0xc0;
public const int VkNext = 0x22;
public const int VkPrior = 0x21;
public static readonly HotkeySettings DefaultEditorHotkeyValue = new HotkeySettings(true, false, false, true, VkOem3);
public static readonly HotkeySettings DefaultNextTabHotkeyValue = new HotkeySettings(true, false, false, false, VkNext);
public static readonly HotkeySettings DefaultPrevTabHotkeyValue = new HotkeySettings(true, false, false, false, VkPrior);
public FZConfigProperties()
{
FancyzonesShiftDrag = new BoolProperty(ConfigDefaults.DefaultFancyzonesShiftDrag);
FancyzonesOverrideSnapHotkeys = new BoolProperty();
FancyzonesMouseSwitch = new BoolProperty();
FancyzonesMouseMiddleClickSpanningMultipleZones = new BoolProperty();
FancyzonesMoveWindowsAcrossMonitors = new BoolProperty();
FancyzonesMoveWindowsBasedOnPosition = new BoolProperty();
FancyzonesOverlappingZonesAlgorithm = new IntProperty();
FancyzonesDisplayOrWorkAreaChangeMoveWindows = new BoolProperty(ConfigDefaults.DefaultFancyzonesDisplayOrWorkAreaChangeMoveWindows);
FancyzonesZoneSetChangeMoveWindows = new BoolProperty();
FancyzonesAppLastZoneMoveWindows = new BoolProperty();
FancyzonesOpenWindowOnActiveMonitor = new BoolProperty();
FancyzonesRestoreSize = new BoolProperty();
FancyzonesQuickLayoutSwitch = new BoolProperty(ConfigDefaults.DefaultFancyzonesQuickLayoutSwitch);
FancyzonesFlashZonesOnQuickSwitch = new BoolProperty(ConfigDefaults.DefaultFancyzonesFlashZonesOnQuickSwitch);
UseCursorposEditorStartupscreen = new BoolProperty(ConfigDefaults.DefaultUseCursorposEditorStartupscreen);
FancyzonesShowOnAllMonitors = new BoolProperty();
FancyzonesSpanZonesAcrossMonitors = new BoolProperty();
FancyzonesZoneHighlightColor = new StringProperty(ConfigDefaults.DefaultFancyZonesZoneHighlightColor);
FancyzonesHighlightOpacity = new IntProperty(50);
FancyzonesEditorHotkey = new KeyboardKeysProperty(DefaultEditorHotkeyValue);
FancyzonesWindowSwitching = new BoolProperty(true);
FancyzonesNextTabHotkey = new KeyboardKeysProperty(DefaultNextTabHotkeyValue);
FancyzonesPrevTabHotkey = new KeyboardKeysProperty(DefaultPrevTabHotkeyValue);
FancyzonesMakeDraggedWindowTransparent = new BoolProperty();
FancyzonesAllowPopupWindowSnap = new BoolProperty();
FancyzonesAllowChildWindowSnap = new BoolProperty();
FancyzonesDisableRoundCornersOnSnap = new BoolProperty();
FancyzonesExcludedApps = new StringProperty();
FancyzonesInActiveColor = new StringProperty(ConfigDefaults.DefaultFancyZonesInActiveColor);
FancyzonesBorderColor = new StringProperty(ConfigDefaults.DefaultFancyzonesBorderColor);
FancyzonesNumberColor = new StringProperty(ConfigDefaults.DefaultFancyzonesNumberColor);
FancyzonesSystemTheme = new BoolProperty(true);
FancyzonesShowZoneNumber = new BoolProperty(true);
}
[JsonPropertyName("fancyzones_shiftDrag")]
public BoolProperty FancyzonesShiftDrag { get; set; }
[JsonPropertyName("fancyzones_mouseSwitch")]
public BoolProperty FancyzonesMouseSwitch { get; set; }
[JsonPropertyName("fancyzones_mouseMiddleClickSpanningMultipleZones")]
public BoolProperty FancyzonesMouseMiddleClickSpanningMultipleZones { get; set; }
[JsonPropertyName("fancyzones_overrideSnapHotkeys")]
public BoolProperty FancyzonesOverrideSnapHotkeys { get; set; }
[JsonPropertyName("fancyzones_moveWindowAcrossMonitors")]
public BoolProperty FancyzonesMoveWindowsAcrossMonitors { get; set; }
[JsonPropertyName("fancyzones_moveWindowsBasedOnPosition")]
public BoolProperty FancyzonesMoveWindowsBasedOnPosition { get; set; }
[JsonPropertyName("fancyzones_overlappingZonesAlgorithm")]
public IntProperty FancyzonesOverlappingZonesAlgorithm { get; set; }
[JsonPropertyName("fancyzones_displayOrWorkAreaChange_moveWindows")]
public BoolProperty FancyzonesDisplayOrWorkAreaChangeMoveWindows { get; set; }
[JsonPropertyName("fancyzones_zoneSetChange_moveWindows")]
public BoolProperty FancyzonesZoneSetChangeMoveWindows { get; set; }
[JsonPropertyName("fancyzones_appLastZone_moveWindows")]
public BoolProperty FancyzonesAppLastZoneMoveWindows { get; set; }
[JsonPropertyName("fancyzones_openWindowOnActiveMonitor")]
public BoolProperty FancyzonesOpenWindowOnActiveMonitor { get; set; }
[JsonPropertyName("fancyzones_restoreSize")]
public BoolProperty FancyzonesRestoreSize { get; set; }
[JsonPropertyName("fancyzones_quickLayoutSwitch")]
public BoolProperty FancyzonesQuickLayoutSwitch { get; set; }
[JsonPropertyName("fancyzones_flashZonesOnQuickSwitch")]
public BoolProperty FancyzonesFlashZonesOnQuickSwitch { get; set; }
[JsonPropertyName("use_cursorpos_editor_startupscreen")]
public BoolProperty UseCursorposEditorStartupscreen { get; set; }
[JsonPropertyName("fancyzones_show_on_all_monitors")]
public BoolProperty FancyzonesShowOnAllMonitors { get; set; }
[JsonPropertyName("fancyzones_span_zones_across_monitors")]
public BoolProperty FancyzonesSpanZonesAcrossMonitors { get; set; }
[JsonPropertyName("fancyzones_makeDraggedWindowTransparent")]
public BoolProperty FancyzonesMakeDraggedWindowTransparent { get; set; }
[JsonPropertyName("fancyzones_allowPopupWindowSnap")]
[CmdConfigureIgnore]
public BoolProperty FancyzonesAllowPopupWindowSnap { get; set; }
[JsonPropertyName("fancyzones_allowChildWindowSnap")]
public BoolProperty FancyzonesAllowChildWindowSnap { get; set; }
[JsonPropertyName("fancyzones_disableRoundCornersOnSnap")]
public BoolProperty FancyzonesDisableRoundCornersOnSnap { get; set; }
[JsonPropertyName("fancyzones_zoneHighlightColor")]
public StringProperty FancyzonesZoneHighlightColor { get; set; }
[JsonPropertyName("fancyzones_highlight_opacity")]
public IntProperty FancyzonesHighlightOpacity { get; set; }
[JsonPropertyName("fancyzones_editor_hotkey")]
public KeyboardKeysProperty FancyzonesEditorHotkey { get; set; }
[JsonPropertyName("fancyzones_windowSwitching")]
public BoolProperty FancyzonesWindowSwitching { get; set; }
[JsonPropertyName("fancyzones_nextTab_hotkey")]
public KeyboardKeysProperty FancyzonesNextTabHotkey { get; set; }
[JsonPropertyName("fancyzones_prevTab_hotkey")]
public KeyboardKeysProperty FancyzonesPrevTabHotkey { get; set; }
[JsonPropertyName("fancyzones_excluded_apps")]
public StringProperty FancyzonesExcludedApps { get; set; }
[JsonPropertyName("fancyzones_zoneBorderColor")]
public StringProperty FancyzonesBorderColor { get; set; }
[JsonPropertyName("fancyzones_zoneColor")]
public StringProperty FancyzonesInActiveColor { get; set; }
[JsonPropertyName("fancyzones_zoneNumberColor")]
public StringProperty FancyzonesNumberColor { get; set; }
[JsonPropertyName("fancyzones_systemTheme")]
public BoolProperty FancyzonesSystemTheme { get; set; }
[JsonPropertyName("fancyzones_showZoneNumber")]
public BoolProperty FancyzonesShowZoneNumber { get; set; }
// converts the current to a json string.
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}
@@ -0,0 +1,36 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FancyZonesSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "FancyZones";
public FancyZonesSettings()
{
Version = "1.0";
Name = ModuleName;
Properties = new FZConfigProperties();
}
[JsonPropertyName("properties")]
public FZConfigProperties Properties { get; set; }
public string GetModuleName()
{
return Name;
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,40 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FileLocksmithLocalProperties : ISettingsConfig
{
public FileLocksmithLocalProperties()
{
ExtendedContextMenuOnly = false;
}
[JsonPropertyName("showInExtendedContextMenu")]
public bool ExtendedContextMenuOnly { get; set; }
public string ToJsonString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.FileLocksmithLocalProperties);
}
// This function is required to implement the ISettingsConfig interface and obtain the settings configurations.
public string GetModuleName()
{
string moduleName = FileLocksmithSettings.ModuleName;
return moduleName;
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,22 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FileLocksmithProperties
{
public FileLocksmithProperties()
{
ExtendedContextMenuOnly = new BoolProperty(false);
}
[JsonPropertyName("bool_show_extended_menu")]
public BoolProperty ExtendedContextMenuOnly { get; set; }
public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.FileLocksmithProperties);
}
}
@@ -0,0 +1,47 @@
// 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.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FileLocksmithSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "File Locksmith";
public const string ModuleVersion = "1";
[JsonPropertyName("properties")]
public FileLocksmithProperties Properties { get; set; }
public FileLocksmithSettings()
{
Name = ModuleName;
Version = ModuleVersion;
Properties = new FileLocksmithProperties();
}
public FileLocksmithSettings(FileLocksmithLocalProperties localProperties)
{
ArgumentNullException.ThrowIfNull(localProperties);
Properties = new FileLocksmithProperties();
Properties.ExtendedContextMenuOnly.Value = localProperties.ExtendedContextMenuOnly;
Version = "1";
Name = ModuleName;
}
public string GetModuleName()
{
return Name;
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,72 @@
// 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.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FindMyMouseProperties
{
[CmdConfigureIgnore]
public HotkeySettings DefaultActivationShortcut => new HotkeySettings(true, false, false, true, 0x46);
[JsonPropertyName("activation_method")]
public IntProperty ActivationMethod { get; set; }
[JsonPropertyName("include_win_key")]
public BoolProperty IncludeWinKey { get; set; }
[JsonPropertyName("activation_shortcut")]
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("do_not_activate_on_game_mode")]
public BoolProperty DoNotActivateOnGameMode { get; set; }
[JsonPropertyName("background_color")]
public StringProperty BackgroundColor { get; set; }
[JsonPropertyName("spotlight_color")]
public StringProperty SpotlightColor { get; set; }
[JsonPropertyName("spotlight_radius")]
public IntProperty SpotlightRadius { get; set; }
[JsonPropertyName("animation_duration_ms")]
public IntProperty AnimationDurationMs { get; set; }
[JsonPropertyName("spotlight_initial_zoom")]
public IntProperty SpotlightInitialZoom { get; set; }
[JsonPropertyName("excluded_apps")]
public StringProperty ExcludedApps { get; set; }
[JsonPropertyName("shaking_minimum_distance")]
public IntProperty ShakingMinimumDistance { get; set; }
[JsonPropertyName("shaking_interval_ms")]
public IntProperty ShakingIntervalMs { get; set; }
[JsonPropertyName("shaking_factor")]
public IntProperty ShakingFactor { get; set; }
public FindMyMouseProperties()
{
ActivationMethod = new IntProperty(0);
IncludeWinKey = new BoolProperty(false);
ActivationShortcut = DefaultActivationShortcut;
DoNotActivateOnGameMode = new BoolProperty(true);
BackgroundColor = new StringProperty("#80000000"); // ARGB (#AARRGGBB)
SpotlightColor = new StringProperty("#80FFFFFF");
SpotlightRadius = new IntProperty(100);
AnimationDurationMs = new IntProperty(500);
SpotlightInitialZoom = new IntProperty(9);
ExcludedApps = new StringProperty();
ShakingMinimumDistance = new IntProperty(1000);
ShakingIntervalMs = new IntProperty(1000);
ShakingFactor = new IntProperty(400);
}
}
}
@@ -0,0 +1,64 @@
// 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.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FindMyMouseSettings : BasePTModuleSettings, ISettingsConfig, IHotkeyConfig
{
public const string ModuleName = "FindMyMouse";
[JsonPropertyName("properties")]
public FindMyMouseProperties Properties { get; set; }
public FindMyMouseSettings()
{
Name = ModuleName;
Properties = new FindMyMouseProperties();
Version = "1.1";
}
public string GetModuleName()
{
return Name;
}
public ModuleType GetModuleType() => ModuleType.FindMyMouse;
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
var hotkeyAccessors = new List<HotkeyAccessor>
{
new HotkeyAccessor(
() => Properties.ActivationShortcut,
value => Properties.ActivationShortcut = value ?? Properties.DefaultActivationShortcut,
"MouseUtils_FindMyMouse_ActivationShortcut"),
};
return hotkeyAccessors.ToArray();
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
if (Version == "1.0")
{
if (Properties.ActivationMethod.Value == 1)
{
Properties.ActivationMethod = new IntProperty(2);
}
Version = "1.1";
return true;
}
return false;
}
}
}
@@ -0,0 +1,29 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FindMyMouseSettingsIPCMessage
{
[JsonPropertyName("powertoys")]
public SndFindMyMouseSettings Powertoys { get; set; }
public FindMyMouseSettingsIPCMessage()
{
}
public FindMyMouseSettingsIPCMessage(SndFindMyMouseSettings settings)
{
this.Powertoys = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}
@@ -0,0 +1,200 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public enum DashboardSortOrder
{
Alphabetical,
ByStatus,
}
public class GeneralSettings : ISettingsConfig, IHotkeyConfig
{
// Gets or sets a value indicating whether run powertoys on start-up.
[JsonPropertyName("startup")]
public bool Startup { get; set; }
// Gets or sets a value indicating whether the powertoys system tray icon should be hidden.
[JsonPropertyName("show_tray_icon")]
public bool ShowSysTrayIcon { get; set; }
// Gets or sets a value indicating whether the powertoys system tray icon should show a theme adaptive icon
[JsonPropertyName("show_theme_adaptive_tray_icon")]
public bool ShowThemeAdaptiveTrayIcon { get; set; }
// Gets or sets a value indicating whether the powertoy elevated.
[CmdConfigureIgnoreAttribute]
[JsonPropertyName("is_elevated")]
public bool IsElevated { get; set; }
// Gets or sets a value indicating whether powertoys should run elevated.
[JsonPropertyName("run_elevated")]
[CmdConfigureIgnoreAttribute]
public bool RunElevated { get; set; }
// Gets or sets a value indicating whether is admin.
[JsonPropertyName("is_admin")]
[CmdConfigureIgnoreAttribute]
public bool IsAdmin { get; set; }
// Gets or sets a value indicating whether is warnings of elevated apps enabled.
[JsonPropertyName("enable_warnings_elevated_apps")]
public bool EnableWarningsElevatedApps { get; set; }
// Gets or sets a value indicating whether Quick Access is enabled.
[JsonPropertyName("enable_quick_access")]
public bool EnableQuickAccess { get; set; }
// Gets or sets Quick Access shortcut.
[JsonPropertyName("quick_access_shortcut")]
public HotkeySettings QuickAccessShortcut { get; set; }
// Gets or sets theme Name.
[JsonPropertyName("theme")]
public string Theme { get; set; }
// Gets or sets system theme name.
[JsonPropertyName("system_theme")]
[CmdConfigureIgnore]
public string SystemTheme { get; set; }
// Gets or sets powertoys version number.
[JsonPropertyName("powertoys_version")]
[CmdConfigureIgnore]
public string PowertoysVersion { get; set; }
[JsonPropertyName("action_name")]
[CmdConfigureIgnore]
public string CustomActionName { get; set; }
[JsonPropertyName("enabled")]
[CmdConfigureIgnore]
public EnabledModules Enabled { get; set; }
[JsonPropertyName("show_new_updates_toast_notification")]
public bool ShowNewUpdatesToastNotification { get; set; }
[JsonPropertyName("download_updates_automatically")]
public bool AutoDownloadUpdates { get; set; }
[JsonPropertyName("show_whats_new_after_updates")]
public bool ShowWhatsNewAfterUpdates { get; set; }
[JsonPropertyName("enable_experimentation")]
public bool EnableExperimentation { get; set; }
[JsonPropertyName("dashboard_sort_order")]
public DashboardSortOrder DashboardSortOrder { get; set; }
[JsonPropertyName("ignored_conflict_properties")]
public ShortcutConflictProperties IgnoredConflictProperties { get; set; }
public GeneralSettings()
{
Startup = false;
ShowSysTrayIcon = true;
IsAdmin = false;
EnableWarningsElevatedApps = true;
EnableQuickAccess = true;
QuickAccessShortcut = new HotkeySettings();
IsElevated = false;
ShowNewUpdatesToastNotification = true;
AutoDownloadUpdates = true;
EnableExperimentation = true;
DashboardSortOrder = DashboardSortOrder.Alphabetical;
Theme = "system";
SystemTheme = "light";
try
{
PowertoysVersion = DefaultPowertoysVersion();
}
catch (Exception e)
{
Logger.LogError("Exception encountered when getting PowerToys version", e);
PowertoysVersion = "v0.0.0";
}
Enabled = new EnabledModules();
CustomActionName = string.Empty;
IgnoredConflictProperties = new ShortcutConflictProperties();
}
public HotkeyAccessor[] GetAllHotkeyAccessors()
{
return new HotkeyAccessor[]
{
new HotkeyAccessor(
() => QuickAccessShortcut,
(hotkey) => { QuickAccessShortcut = hotkey; },
"GeneralPage_QuickAccessShortcut"),
};
}
public ModuleType GetModuleType()
{
return ModuleType.GeneralSettings;
}
// converts the current to a json string.
public string ToJsonString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettings);
}
private static string DefaultPowertoysVersion()
{
return global::PowerToys.Interop.CommonManaged.GetProductVersion();
}
// This function is to implement the ISettingsConfig interface.
// This interface helps in getting the settings configurations.
public string GetModuleName()
{
// The SettingsUtils functions access general settings when the module name is an empty string.
return string.Empty;
}
public bool UpgradeSettingsConfiguration()
{
try
{
if (Helper.CompareVersions(PowertoysVersion, Helper.GetProductVersion()) != 0)
{
// Update settings
PowertoysVersion = Helper.GetProductVersion();
return true;
}
}
catch (FormatException)
{
// If there is an issue with the version number format, don't migrate settings.
}
// Ensure IgnoredConflictProperties is initialized (for backward compatibility)
if (IgnoredConflictProperties == null)
{
IgnoredConflictProperties = new ShortcutConflictProperties();
return true; // Indicate that settings were upgraded
}
return false;
}
public void AddEnabledModuleChangeNotification(Action callBack)
{
Enabled.AddEnabledModuleChangeNotification(callBack);
}
}
}
@@ -0,0 +1,29 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class GeneralSettingsCustomAction
{
[JsonPropertyName("action")]
public OutGoingGeneralSettings GeneralSettingsAction { get; set; }
public GeneralSettingsCustomAction()
{
}
public GeneralSettingsCustomAction(OutGoingGeneralSettings action)
{
GeneralSettingsAction = action;
}
public override string ToString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettingsCustomAction);
}
}
}
@@ -0,0 +1,45 @@
// 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.Text.Json.Serialization;
using System.Text.RegularExpressions;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class GenericProperty<T> : ICmdLineRepresentable
{
[JsonPropertyName("value")]
public T Value { get; set; }
public GenericProperty(T value)
{
Value = value;
}
// Added a parameterless constructor because of an exception during deserialization. More details here: https://learn.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#deserialization-behavior
public GenericProperty()
{
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1000:Do not declare static members on generic types", Justification = "Adding ICmdLineRepresentable support")]
public static bool TryParseFromCmd(string cmd, out object result)
{
result = null;
if (ICmdLineRepresentable.TryParseFromCmdFor(typeof(T), cmd, out var value))
{
result = new GenericProperty<T> { Value = (T)value };
return true;
}
return false;
}
public bool TryToCmdRepresentable(out string result)
{
result = Value.ToString();
return true;
}
}
}
@@ -0,0 +1,39 @@
// 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.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class GrabAndMoveProperties
{
public GrabAndMoveProperties()
{
ShouldAbsorbAlt = new BoolProperty(true);
DoNotActivateOnGameMode = new BoolProperty(true);
ShowGeometry = new BoolProperty(false);
UseAltResize = new BoolProperty(true);
ExcludedApps = new StringProperty();
ModifierKey = new IntProperty(0); // 0 = Alt, 1 = Win
}
[JsonPropertyName("modifierKey")]
public IntProperty ModifierKey { get; set; }
[JsonPropertyName("shouldAbsorbAlt")]
public BoolProperty ShouldAbsorbAlt { get; set; }
[JsonPropertyName("showGeometry")]
public BoolProperty ShowGeometry { get; set; }
[JsonPropertyName("useAltResize")]
public BoolProperty UseAltResize { get; set; }
[JsonPropertyName("doNotActivateOnGameMode")]
public BoolProperty DoNotActivateOnGameMode { get; set; }
[JsonPropertyName("excluded_apps")]
public StringProperty ExcludedApps { get; set; }
}
}
@@ -0,0 +1,32 @@
// 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.Reflection;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class GrabAndMoveSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "GrabAndMove";
public GrabAndMoveSettings()
{
Name = ModuleName;
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Properties = new GrabAndMoveProperties();
}
[JsonPropertyName("properties")]
public GrabAndMoveProperties Properties { get; set; }
public string GetModuleName() => Name;
public bool UpgradeSettingsConfiguration() => false;
public ModuleType GetModuleType() => ModuleType.GrabAndMove;
}
}
@@ -0,0 +1,70 @@
// 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.Drawing;
using global::Settings.UI.Library.Resources;
using ManagedCommon;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public static class ColorNameHelper
{
public static string GetColorNameFromColorIdentifier(string colorIdentifier)
{
switch (colorIdentifier)
{
case "TEXT_COLOR_WHITE": return Resources.TEXT_COLOR_WHITE;
case "TEXT_COLOR_BLACK": return Resources.TEXT_COLOR_BLACK;
case "TEXT_COLOR_LIGHTGRAY": return Resources.TEXT_COLOR_LIGHTGRAY;
case "TEXT_COLOR_GRAY": return Resources.TEXT_COLOR_GRAY;
case "TEXT_COLOR_DARKGRAY": return Resources.TEXT_COLOR_DARKGRAY;
case "TEXT_COLOR_CORAL": return Resources.TEXT_COLOR_CORAL;
case "TEXT_COLOR_ROSE": return Resources.TEXT_COLOR_ROSE;
case "TEXT_COLOR_LIGHTORANGE": return Resources.TEXT_COLOR_LIGHTORANGE;
case "TEXT_COLOR_TAN": return Resources.TEXT_COLOR_TAN;
case "TEXT_COLOR_LIGHTYELLOW": return Resources.TEXT_COLOR_LIGHTYELLOW;
case "TEXT_COLOR_LIGHTGREEN": return Resources.TEXT_COLOR_LIGHTGREEN;
case "TEXT_COLOR_LIME": return Resources.TEXT_COLOR_LIME;
case "TEXT_COLOR_AQUA": return Resources.TEXT_COLOR_AQUA;
case "TEXT_COLOR_SKYBLUE": return Resources.TEXT_COLOR_SKYBLUE;
case "TEXT_COLOR_LIGHTTURQUOISE": return Resources.TEXT_COLOR_LIGHTTURQUOISE;
case "TEXT_COLOR_PALEBLUE": return Resources.TEXT_COLOR_PALEBLUE;
case "TEXT_COLOR_LIGHTBLUE": return Resources.TEXT_COLOR_LIGHTBLUE;
case "TEXT_COLOR_ICEBLUE": return Resources.TEXT_COLOR_ICEBLUE;
case "TEXT_COLOR_PERIWINKLE": return Resources.TEXT_COLOR_PERIWINKLE;
case "TEXT_COLOR_LAVENDER": return Resources.TEXT_COLOR_LAVENDER;
case "TEXT_COLOR_PINK": return Resources.TEXT_COLOR_PINK;
case "TEXT_COLOR_RED": return Resources.TEXT_COLOR_RED;
case "TEXT_COLOR_ORANGE": return Resources.TEXT_COLOR_ORANGE;
case "TEXT_COLOR_BROWN": return Resources.TEXT_COLOR_BROWN;
case "TEXT_COLOR_GOLD": return Resources.TEXT_COLOR_GOLD;
case "TEXT_COLOR_YELLOW": return Resources.TEXT_COLOR_YELLOW;
case "TEXT_COLOR_OLIVEGREEN": return Resources.TEXT_COLOR_OLIVEGREEN;
case "TEXT_COLOR_GREEN": return Resources.TEXT_COLOR_GREEN;
case "TEXT_COLOR_BRIGHTGREEN": return Resources.TEXT_COLOR_BRIGHTGREEN;
case "TEXT_COLOR_TEAL": return Resources.TEXT_COLOR_TEAL;
case "TEXT_COLOR_TURQUOISE": return Resources.TEXT_COLOR_TURQUOISE;
case "TEXT_COLOR_BLUE": return Resources.TEXT_COLOR_BLUE;
case "TEXT_COLOR_BLUEGRAY": return Resources.TEXT_COLOR_BLUEGRAY;
case "TEXT_COLOR_INDIGO": return Resources.TEXT_COLOR_INDIGO;
case "TEXT_COLOR_PURPLE": return Resources.TEXT_COLOR_PURPLE;
case "TEXT_COLOR_DARKRED": return Resources.TEXT_COLOR_DARKRED;
case "TEXT_COLOR_DARKYELLOW": return Resources.TEXT_COLOR_DARKYELLOW;
case "TEXT_COLOR_DARKGREEN": return Resources.TEXT_COLOR_DARKGREEN;
case "TEXT_COLOR_DARKTEAL": return Resources.TEXT_COLOR_DARKTEAL;
case "TEXT_COLOR_DARKBLUE": return Resources.TEXT_COLOR_DARKBLUE;
case "TEXT_COLOR_DARKPURPLE": return Resources.TEXT_COLOR_DARKPURPLE;
case "TEXT_COLOR_PLUM": return Resources.TEXT_COLOR_PLUM;
default: return colorIdentifier;
}
}
public static string ReplaceName(string colorFormat, Color? colorOrNull)
{
Color color = (Color)(colorOrNull == null ? Color.Moccasin : colorOrNull);
return colorFormat.Replace(ColorFormatHelper.GetColorNameParameter(), GetColorNameFromColorIdentifier(ManagedCommon.ColorNameHelper.GetColorNameIdentifier(color)));
}
}
}
@@ -0,0 +1,34 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public class HotkeyAccessor
{
public Func<HotkeySettings> Getter { get; }
public Action<HotkeySettings> Setter { get; }
public HotkeyAccessor(Func<HotkeySettings> getter, Action<HotkeySettings> setter, string localizationHeaderKey = "")
{
Getter = getter ?? throw new ArgumentNullException(nameof(getter));
Setter = setter ?? throw new ArgumentNullException(nameof(setter));
LocalizationHeaderKey = localizationHeaderKey;
}
public HotkeySettings Value
{
get => Getter();
set => Setter(value);
}
public string LocalizationHeaderKey { get; set; }
}
}
@@ -0,0 +1,169 @@
// 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 ManagedCommon;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public static class ModuleHelper
{
public static string GetModuleLabelResourceName(ModuleType moduleType)
{
return moduleType switch
{
ModuleType.Workspaces => "Workspaces/ModuleTitle",
ModuleType.PowerAccent => "QuickAccent/ModuleTitle",
ModuleType.PowerOCR => "TextExtractor/ModuleTitle",
ModuleType.FindMyMouse => "MouseUtils_FindMyMouse/Header",
ModuleType.MouseHighlighter => "MouseUtils_MouseHighlighter/Header",
ModuleType.MouseJump => "MouseUtils_MouseJump/Header",
ModuleType.MousePointerCrosshairs => "MouseUtils_MousePointerCrosshairs/Header",
ModuleType.CursorWrap => "MouseUtils_CursorWrap/Header",
ModuleType.GeneralSettings => "QuickAccessTitle/Title",
_ => $"{moduleType}/ModuleTitle",
};
}
public static string GetModuleTypeFluentIconName(ModuleType moduleType)
{
return moduleType switch
{
ModuleType.AdvancedPaste => "ms-appx:///Assets/Settings/Icons/AdvancedPaste.png",
ModuleType.Workspaces => "ms-appx:///Assets/Settings/Icons/Workspaces.png",
ModuleType.PowerOCR => "ms-appx:///Assets/Settings/Icons/TextExtractor.png",
ModuleType.PowerAccent => "ms-appx:///Assets/Settings/Icons/QuickAccent.png",
ModuleType.MousePointerCrosshairs => "ms-appx:///Assets/Settings/Icons/MouseCrosshairs.png",
ModuleType.MeasureTool => "ms-appx:///Assets/Settings/Icons/ScreenRuler.png",
ModuleType.PowerLauncher => "ms-appx:///Assets/Settings/Icons/PowerToysRun.png",
ModuleType.GeneralSettings => "ms-appx:///Assets/Settings/Icons/PowerToys.png",
_ => $"ms-appx:///Assets/Settings/Icons/{moduleType}.png",
};
}
public static bool GetIsModuleEnabled(GeneralSettings generalSettingsConfig, ModuleType moduleType)
{
return moduleType switch
{
ModuleType.AdvancedPaste => generalSettingsConfig.Enabled.AdvancedPaste,
ModuleType.AlwaysOnTop => generalSettingsConfig.Enabled.AlwaysOnTop,
ModuleType.Awake => generalSettingsConfig.Enabled.Awake,
ModuleType.CmdPal => generalSettingsConfig.Enabled.CmdPal,
ModuleType.ColorPicker => generalSettingsConfig.Enabled.ColorPicker,
ModuleType.CropAndLock => generalSettingsConfig.Enabled.CropAndLock,
ModuleType.CursorWrap => generalSettingsConfig.Enabled.CursorWrap,
ModuleType.EnvironmentVariables => generalSettingsConfig.Enabled.EnvironmentVariables,
ModuleType.FancyZones => generalSettingsConfig.Enabled.FancyZones,
ModuleType.FileLocksmith => generalSettingsConfig.Enabled.FileLocksmith,
ModuleType.FindMyMouse => generalSettingsConfig.Enabled.FindMyMouse,
ModuleType.Hosts => generalSettingsConfig.Enabled.Hosts,
ModuleType.ImageResizer => generalSettingsConfig.Enabled.ImageResizer,
ModuleType.KeyboardManager => generalSettingsConfig.Enabled.KeyboardManager,
ModuleType.LightSwitch => generalSettingsConfig.Enabled.LightSwitch,
ModuleType.MouseHighlighter => generalSettingsConfig.Enabled.MouseHighlighter,
ModuleType.MouseJump => generalSettingsConfig.Enabled.MouseJump,
ModuleType.MousePointerCrosshairs => generalSettingsConfig.Enabled.MousePointerCrosshairs,
ModuleType.MouseWithoutBorders => generalSettingsConfig.Enabled.MouseWithoutBorders,
ModuleType.NewPlus => generalSettingsConfig.Enabled.NewPlus,
ModuleType.Peek => generalSettingsConfig.Enabled.Peek,
ModuleType.PowerRename => generalSettingsConfig.Enabled.PowerRename,
ModuleType.PowerLauncher => generalSettingsConfig.Enabled.PowerLauncher,
ModuleType.PowerAccent => generalSettingsConfig.Enabled.PowerAccent,
ModuleType.RegistryPreview => generalSettingsConfig.Enabled.RegistryPreview,
ModuleType.MeasureTool => generalSettingsConfig.Enabled.MeasureTool,
ModuleType.ShortcutGuide => generalSettingsConfig.Enabled.ShortcutGuide,
ModuleType.PowerOCR => generalSettingsConfig.Enabled.PowerOcr,
ModuleType.PowerDisplay => generalSettingsConfig.Enabled.PowerDisplay,
ModuleType.Workspaces => generalSettingsConfig.Enabled.Workspaces,
ModuleType.GrabAndMove => generalSettingsConfig.Enabled.GrabAndMove,
ModuleType.ZoomIt => generalSettingsConfig.Enabled.ZoomIt,
ModuleType.GeneralSettings => generalSettingsConfig.EnableQuickAccess,
_ => false,
};
}
public static void SetIsModuleEnabled(GeneralSettings generalSettingsConfig, ModuleType moduleType, bool isEnabled)
{
switch (moduleType)
{
case ModuleType.AdvancedPaste: generalSettingsConfig.Enabled.AdvancedPaste = isEnabled; break;
case ModuleType.AlwaysOnTop: generalSettingsConfig.Enabled.AlwaysOnTop = isEnabled; break;
case ModuleType.Awake: generalSettingsConfig.Enabled.Awake = isEnabled; break;
case ModuleType.CmdPal: generalSettingsConfig.Enabled.CmdPal = isEnabled; break;
case ModuleType.ColorPicker: generalSettingsConfig.Enabled.ColorPicker = isEnabled; break;
case ModuleType.CropAndLock: generalSettingsConfig.Enabled.CropAndLock = isEnabled; break;
case ModuleType.CursorWrap: generalSettingsConfig.Enabled.CursorWrap = isEnabled; break;
case ModuleType.EnvironmentVariables: generalSettingsConfig.Enabled.EnvironmentVariables = isEnabled; break;
case ModuleType.FancyZones: generalSettingsConfig.Enabled.FancyZones = isEnabled; break;
case ModuleType.FileLocksmith: generalSettingsConfig.Enabled.FileLocksmith = isEnabled; break;
case ModuleType.FindMyMouse: generalSettingsConfig.Enabled.FindMyMouse = isEnabled; break;
case ModuleType.Hosts: generalSettingsConfig.Enabled.Hosts = isEnabled; break;
case ModuleType.ImageResizer: generalSettingsConfig.Enabled.ImageResizer = isEnabled; break;
case ModuleType.KeyboardManager: generalSettingsConfig.Enabled.KeyboardManager = isEnabled; break;
case ModuleType.LightSwitch: generalSettingsConfig.Enabled.LightSwitch = isEnabled; break;
case ModuleType.MouseHighlighter: generalSettingsConfig.Enabled.MouseHighlighter = isEnabled; break;
case ModuleType.MouseJump: generalSettingsConfig.Enabled.MouseJump = isEnabled; break;
case ModuleType.MousePointerCrosshairs: generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
case ModuleType.MouseWithoutBorders: generalSettingsConfig.Enabled.MouseWithoutBorders = isEnabled; break;
case ModuleType.NewPlus: generalSettingsConfig.Enabled.NewPlus = isEnabled; break;
case ModuleType.Peek: generalSettingsConfig.Enabled.Peek = isEnabled; break;
case ModuleType.PowerRename: generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
case ModuleType.PowerLauncher: generalSettingsConfig.Enabled.PowerLauncher = isEnabled; break;
case ModuleType.PowerAccent: generalSettingsConfig.Enabled.PowerAccent = isEnabled; break;
case ModuleType.RegistryPreview: generalSettingsConfig.Enabled.RegistryPreview = isEnabled; break;
case ModuleType.MeasureTool: generalSettingsConfig.Enabled.MeasureTool = isEnabled; break;
case ModuleType.ShortcutGuide: generalSettingsConfig.Enabled.ShortcutGuide = isEnabled; break;
case ModuleType.PowerOCR: generalSettingsConfig.Enabled.PowerOcr = isEnabled; break;
case ModuleType.PowerDisplay: generalSettingsConfig.Enabled.PowerDisplay = isEnabled; break;
case ModuleType.Workspaces: generalSettingsConfig.Enabled.Workspaces = isEnabled; break;
case ModuleType.GrabAndMove: generalSettingsConfig.Enabled.GrabAndMove = isEnabled; break;
case ModuleType.ZoomIt: generalSettingsConfig.Enabled.ZoomIt = isEnabled; break;
case ModuleType.GeneralSettings: generalSettingsConfig.EnableQuickAccess = isEnabled; break;
}
}
/// <summary>
/// Gets the module key name used in IPC messages and settings JSON.
/// These names match the JsonPropertyName attributes in EnabledModules class.
/// </summary>
public static string GetModuleKey(ModuleType moduleType)
{
return moduleType switch
{
ModuleType.AdvancedPaste => AdvancedPasteSettings.ModuleName,
ModuleType.AlwaysOnTop => AlwaysOnTopSettings.ModuleName,
ModuleType.Awake => AwakeSettings.ModuleName,
ModuleType.CmdPal => "CmdPal", // No dedicated settings class
ModuleType.ColorPicker => ColorPickerSettings.ModuleName,
ModuleType.CropAndLock => CropAndLockSettings.ModuleName,
ModuleType.CursorWrap => CursorWrapSettings.ModuleName,
ModuleType.EnvironmentVariables => EnvironmentVariablesSettings.ModuleName,
ModuleType.FancyZones => FancyZonesSettings.ModuleName,
ModuleType.FileLocksmith => FileLocksmithSettings.ModuleName,
ModuleType.FindMyMouse => FindMyMouseSettings.ModuleName,
ModuleType.Hosts => HostsSettings.ModuleName,
ModuleType.ImageResizer => ImageResizerSettings.ModuleName,
ModuleType.KeyboardManager => KeyboardManagerSettings.ModuleName,
ModuleType.LightSwitch => LightSwitchSettings.ModuleName,
ModuleType.MouseHighlighter => MouseHighlighterSettings.ModuleName,
ModuleType.MouseJump => MouseJumpSettings.ModuleName,
ModuleType.MousePointerCrosshairs => MousePointerCrosshairsSettings.ModuleName,
ModuleType.MouseWithoutBorders => MouseWithoutBordersSettings.ModuleName,
ModuleType.NewPlus => NewPlusSettings.ModuleName,
ModuleType.Peek => PeekSettings.ModuleName,
ModuleType.PowerRename => PowerRenameSettings.ModuleName,
ModuleType.PowerLauncher => PowerLauncherSettings.ModuleName,
ModuleType.PowerAccent => PowerAccentSettings.ModuleName,
ModuleType.PowerDisplay => PowerDisplaySettings.ModuleName,
ModuleType.RegistryPreview => RegistryPreviewSettings.ModuleName,
ModuleType.MeasureTool => MeasureToolSettings.ModuleName,
ModuleType.ShortcutGuide => ShortcutGuideSettings.ModuleName,
ModuleType.PowerOCR => PowerOcrSettings.ModuleName,
ModuleType.Workspaces => WorkspacesSettings.ModuleName,
ModuleType.GrabAndMove => GrabAndMoveSettings.ModuleName,
ModuleType.ZoomIt => ZoomItSettings.ModuleName,
_ => moduleType.ToString(),
};
}
}
}
@@ -0,0 +1,29 @@
// 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.ComponentModel;
using System.Runtime.CompilerServices;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public class Observable : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
@@ -0,0 +1,31 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Settings.UI.Library.Helpers
{
public class SearchLocation
{
public string City { get; set; }
public string Country { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public SearchLocation(string city, string country, double latitude, double longitude)
{
City = city;
Country = country;
Latitude = latitude;
Longitude = longitude;
}
}
}
@@ -0,0 +1,28 @@
// 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.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Settings.UI.Library.Helpers;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public static class SearchLocationLoader
{
private static readonly List<SearchLocation> LocationDataList = new List<SearchLocation>();
public static IEnumerable<SearchLocation> GetAll()
{
return LocationDataList
.GroupBy(l => $"{l.Country}|{l.City}|{l.Latitude.ToString(CultureInfo.InvariantCulture)}|{l.Longitude.ToString(CultureInfo.InvariantCulture)}")
.Select(g => g.First())
.OrderBy(l => l.Country, StringComparer.OrdinalIgnoreCase)
.ThenBy(l => l.City, StringComparer.OrdinalIgnoreCase);
}
}
}
@@ -0,0 +1,67 @@
// 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.Drawing;
using System.Globalization;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public static class SettingsUtilities
{
public static string ToRGBHex(string color)
{
if (color == null)
{
return "#FFFFFF";
}
// Using InvariantCulture as these are expected to be hex codes.
bool success = int.TryParse(
color.Replace("#", string.Empty),
System.Globalization.NumberStyles.HexNumber,
CultureInfo.InvariantCulture,
out int argb);
if (success)
{
Color clr = Color.FromArgb(argb);
return "#" + clr.R.ToString("X2", CultureInfo.InvariantCulture) +
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
clr.B.ToString("X2", CultureInfo.InvariantCulture);
}
else
{
return "#FFFFFF";
}
}
public static string ToARGBHex(string color)
{
if (color == null)
{
return "#FFFFFFFF";
}
// Using InvariantCulture as these are expected to be hex codes.
bool success = int.TryParse(
color.Replace("#", string.Empty),
System.Globalization.NumberStyles.HexNumber,
CultureInfo.InvariantCulture,
out int argb);
if (success)
{
Color clr = Color.FromArgb(argb);
return "#" + clr.A.ToString("X2", CultureInfo.InvariantCulture) +
clr.R.ToString("X2", CultureInfo.InvariantCulture) +
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
clr.B.ToString("X2", CultureInfo.InvariantCulture);
}
else
{
return "#FFFFFFFF";
}
}
}
}
@@ -0,0 +1,131 @@
// 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;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public static class SunCalc
{
public static SunTimes CalculateSunriseSunset(double latitude, double longitude, int year, int month, int day)
{
double zenith = 90.833; // official sunrise/sunset
int n1 = (int)Math.Floor(275.0 * month / 9.0);
int n2 = (int)Math.Floor((month + 9.0) / 12.0);
int n3 = (int)Math.Floor(1.0 + Math.Floor((year - (4.0 * Math.Floor(year / 4.0)) + 2.0) / 3.0));
int n = n1 - (n2 * n3) + day - 30;
double? riseUT = CalcTime(isSunrise: true);
double? setUT = CalcTime(isSunrise: false);
var riseLocal = ToLocal(riseUT, year, month, day);
var setLocal = ToLocal(setUT, year, month, day);
var result = new SunTimes
{
HasSunrise = riseLocal.HasValue,
HasSunset = setLocal.HasValue,
SunriseHour = riseLocal?.Hour ?? -1,
SunriseMinute = riseLocal?.Minute ?? -1,
SunsetHour = setLocal?.Hour ?? -1,
SunsetMinute = setLocal?.Minute ?? -1,
};
return result;
// Local functions
double? CalcTime(bool isSunrise)
{
double lngHour = longitude / 15.0;
double t = isSunrise ? n + ((6 - lngHour) / 24.0) : n + ((18 - lngHour) / 24.0);
double m1 = (0.9856 * t) - 3.289;
double l = m1 + (1.916 * Math.Sin(Deg2Rad(m1))) + (0.020 * Math.Sin(2 * Deg2Rad(m1))) + 282.634;
l = NormalizeDegrees(l);
double rA = Rad2Deg(Math.Atan(0.91764 * Math.Tan(Deg2Rad(l))));
rA = NormalizeDegrees(rA);
double lquadrant = Math.Floor(l / 90.0) * 90.0;
double rAquadrant = Math.Floor(rA / 90.0) * 90.0;
rA = rA + (lquadrant - rAquadrant);
rA /= 15.0;
double sinDec = 0.39782 * Math.Sin(Deg2Rad(l));
double cosDec = Math.Cos(Math.Asin(sinDec));
double cosH = (Math.Cos(Deg2Rad(zenith)) - (sinDec * Math.Sin(Deg2Rad(latitude))))
/ (cosDec * Math.Cos(Deg2Rad(latitude)));
if (cosH > 1.0 || cosH < -1.0)
{
// Sun never rises or never sets on this date at this location
return null;
}
double h = isSunrise ? 360.0 - Rad2Deg(Math.Acos(cosH)) : Rad2Deg(Math.Acos(cosH));
h /= 15.0;
double t1 = h + rA - (0.06571 * t) - 6.622;
double uT = t1 - lngHour;
uT = NormalizeHours(uT);
return uT;
}
static (int Hour, int Minute)? ToLocal(double? ut, int y, int m, int d)
{
if (!ut.HasValue)
{
return null;
}
// Convert fractional hours to hh:mm with proper rounding
int hours = (int)Math.Floor(ut.Value);
int minutes = (int)((ut.Value - hours) * 60.0);
// Normalize minute overflow
if (minutes == 60)
{
minutes = 0;
hours = (hours + 1) % 24;
}
// Build a UTC DateTime on the given date
var utc = new DateTime(y, m, d, hours, minutes, 0, DateTimeKind.Utc);
// Convert to local time using system time zone rules for that date
var local = TimeZoneInfo.ConvertTimeFromUtc(utc, TimeZoneInfo.Local);
return (local.Hour, local.Minute);
}
static double Deg2Rad(double deg) => deg * Math.PI / 180.0;
static double Rad2Deg(double rad) => rad * 180.0 / Math.PI;
static double NormalizeDegrees(double angle)
{
angle %= 360.0;
if (angle < 0)
{
angle += 360.0;
}
return angle;
}
static double NormalizeHours(double hours)
{
hours %= 24.0;
if (hours < 0)
{
hours += 24.0;
}
return hours;
}
}
}
}
@@ -0,0 +1,29 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public struct SunTimes
{
public int SunriseHour { get; set; }
public int SunriseMinute { get; set; }
public int SunsetHour { get; set; }
public int SunsetMinute { get; set; }
public string Text { get; set; }
public bool HasSunrise { get; set; }
public bool HasSunset { get; set; }
}
}
@@ -0,0 +1,56 @@
// 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.IO;
using System.Text.Json.Serialization;
using Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class HostsProperties
{
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ShowStartupWarning { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool LaunchAdministrator { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool LoopbackDuplicates { get; set; }
public HostsAdditionalLinesPosition AdditionalLinesPosition { get; set; }
public HostsEncoding Encoding { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool NoLeadingSpaces { get; set; }
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool BackupHosts { get; set; }
public string BackupPath { get; set; }
public HostsDeleteBackupMode DeleteBackupsMode { get; set; }
public int DeleteBackupsDays { get; set; }
public int DeleteBackupsCount { get; set; }
public HostsProperties()
{
ShowStartupWarning = true;
LaunchAdministrator = true;
LoopbackDuplicates = false;
AdditionalLinesPosition = HostsAdditionalLinesPosition.Top;
Encoding = HostsEncoding.Utf8;
NoLeadingSpaces = false;
BackupHosts = true;
BackupPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"System32\drivers\etc");
DeleteBackupsMode = HostsDeleteBackupMode.Age;
DeleteBackupsDays = 15;
DeleteBackupsCount = 5;
}
}
}
@@ -0,0 +1,46 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class HostsSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "Hosts";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
[JsonPropertyName("properties")]
public HostsProperties Properties { get; set; }
public HostsSettings()
{
Properties = new HostsProperties();
Version = "1.0";
Name = ModuleName;
}
public virtual void Save(SettingsUtils settingsUtils)
{
// Save settings to file
var options = _serializerOptions;
ArgumentNullException.ThrowIfNull(settingsUtils);
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
}
public string GetModuleName() => Name;
public bool UpgradeSettingsConfiguration() => false;
}
}
@@ -0,0 +1,19 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class AllHotkeyConflictsData
{
public List<HotkeyConflictGroupData> InAppConflicts { get; set; } = new List<HotkeyConflictGroupData>();
public List<HotkeyConflictGroupData> SystemConflicts { get; set; } = new List<HotkeyConflictGroupData>();
}
}
@@ -0,0 +1,22 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class AllHotkeyConflictsEventArgs : EventArgs
{
public AllHotkeyConflictsData Conflicts { get; }
public AllHotkeyConflictsEventArgs(AllHotkeyConflictsData conflicts)
{
Conflicts = conflicts;
}
}
}
@@ -0,0 +1,23 @@
// 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;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class HotkeyConflictGroupData
{
public HotkeyData Hotkey { get; set; }
public bool IsSystemConflict { get; set; }
public bool ConflictIgnored { get; set; }
public bool ConflictVisible => !ConflictIgnored;
public bool ShouldShowSysConflict => !ConflictIgnored && IsSystemConflict;
public List<ModuleHotkeyData> Modules { get; set; }
}
}
@@ -0,0 +1,23 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class HotkeyConflictInfo
{
public bool IsSystemConflict { get; set; }
public string ConflictingModuleName { get; set; }
public int ConflictingHotkeyID { get; set; }
public List<string> AllConflictingModules { get; set; } = new List<string>();
}
}
@@ -0,0 +1,71 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class HotkeyData
{
public bool Win { get; set; }
public bool Ctrl { get; set; }
public bool Shift { get; set; }
public bool Alt { get; set; }
public int Key { get; set; }
public List<object> GetKeysList()
{
List<object> shortcutList = new List<object>();
if (Win)
{
shortcutList.Add(92); // The Windows key or button.
}
if (Ctrl)
{
shortcutList.Add("Ctrl");
}
if (Alt)
{
shortcutList.Add("Alt");
}
if (Shift)
{
shortcutList.Add(16); // The Shift key or button.
}
if (Key > 0)
{
switch (Key)
{
// https://learn.microsoft.com/uwp/api/windows.system.virtualkey?view=winrt-20348
case 38: // The Up Arrow key or button.
case 40: // The Down Arrow key or button.
case 37: // The Left Arrow key or button.
case 39: // The Right Arrow key or button.
shortcutList.Add(Key);
break;
default:
var localKey = Helper.GetKeyName((uint)Key);
shortcutList.Add(localKey);
break;
}
}
return shortcutList;
}
}
}
@@ -0,0 +1,21 @@
// 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.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class ModuleConflictsData
{
public List<HotkeyConflictGroupData> InAppConflicts { get; set; } = new List<HotkeyConflictGroupData>();
public List<HotkeyConflictGroupData> SystemConflicts { get; set; } = new List<HotkeyConflictGroupData>();
public bool HasConflicts => InAppConflicts.Count > 0 || SystemConflicts.Count > 0;
}
}
@@ -0,0 +1,84 @@
// 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.ComponentModel;
using System.Runtime.CompilerServices;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Windows.Web.AtomPub;
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
{
public class ModuleHotkeyData : INotifyPropertyChanged
{
private string _moduleName;
private int _hotkeyID;
private HotkeySettings _hotkeySettings;
private bool _isSystemConflict;
public event PropertyChangedEventHandler PropertyChanged;
public string IconPath { get; set; }
public string DisplayName { get; set; }
public string Header { get; set; }
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string ModuleName
{
get => _moduleName;
set
{
if (_moduleName != value)
{
_moduleName = value;
}
}
}
public int HotkeyID
{
get => _hotkeyID;
set
{
if (_hotkeyID != value)
{
_hotkeyID = value;
}
}
}
public HotkeySettings HotkeySettings
{
get => _hotkeySettings;
set
{
if (_hotkeySettings != value)
{
_hotkeySettings = value;
OnPropertyChanged();
}
}
}
public bool IsSystemConflict
{
get => _isSystemConflict;
set
{
if (_isSystemConflict != value)
{
_isSystemConflict = value;
}
}
}
public ModuleType ModuleType { get; set; }
}
}
@@ -0,0 +1,320 @@
// 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.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Json.Serialization;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public record HotkeySettings : ICmdLineRepresentable, INotifyPropertyChanged
{
private const int VKTAB = 0x09;
private bool _hasConflict;
private string _conflictDescription;
private bool _isSystemConflict;
private bool _ignoreConflict;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public HotkeySettings()
{
Win = false;
Ctrl = false;
Alt = false;
Shift = false;
Code = 0;
HasConflict = false;
}
/// <summary>
/// Initializes a new instance of the <see cref="HotkeySettings"/> class.
/// </summary>
/// <param name="win">Should Windows key be used</param>
/// <param name="ctrl">Should Ctrl key be used</param>
/// <param name="alt">Should Alt key be used</param>
/// <param name="shift">Should Shift key be used</param>
/// <param name="code">Go to https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes to see list of v-keys</param>
public HotkeySettings(bool win, bool ctrl, bool alt, bool shift, int code)
{
Win = win;
Ctrl = ctrl;
Alt = alt;
Shift = shift;
Code = code;
HasConflict = false;
}
[JsonIgnore]
public bool IgnoreConflict
{
get => _ignoreConflict;
set
{
if (_ignoreConflict != value)
{
_ignoreConflict = value;
OnPropertyChanged();
}
}
}
[JsonIgnore]
public bool HasConflict
{
get => _hasConflict;
set
{
if (_hasConflict != value)
{
_hasConflict = value;
OnPropertyChanged();
}
}
}
[JsonIgnore]
public string ConflictDescription
{
get => _ignoreConflict ? null : _conflictDescription;
set
{
if (_conflictDescription != value)
{
_conflictDescription = value;
OnPropertyChanged();
}
}
}
[JsonIgnore]
public bool IsSystemConflict
{
get => _isSystemConflict;
set
{
if (_isSystemConflict != value)
{
_isSystemConflict = value;
OnPropertyChanged();
}
}
}
public virtual void UpdateConflictStatus()
{
Logger.LogInfo($"{this.ToString()}");
}
[JsonPropertyName("win")]
public bool Win { get; set; }
[JsonPropertyName("ctrl")]
public bool Ctrl { get; set; }
[JsonPropertyName("alt")]
public bool Alt { get; set; }
[JsonPropertyName("shift")]
public bool Shift { get; set; }
[JsonPropertyName("code")]
public int Code { get; set; }
// This is currently needed for FancyZones, we need to unify these two objects
// see src\common\settings_objects.h
[JsonPropertyName("key")]
public string Key { get; set; } = string.Empty;
public override string ToString()
{
StringBuilder output = new StringBuilder();
if (Win)
{
output.Append("Win + ");
}
if (Ctrl)
{
output.Append("Ctrl + ");
}
if (Alt)
{
output.Append("Alt + ");
}
if (Shift)
{
output.Append("Shift + ");
}
if (Code > 0)
{
var localKey = Helper.GetKeyName((uint)Code);
output.Append(localKey);
}
else if (output.Length >= 2)
{
output.Remove(output.Length - 2, 2);
}
return output.ToString();
}
public List<object> GetKeysList()
{
List<object> shortcutList = new List<object>();
if (Win)
{
shortcutList.Add(92); // The Windows key or button.
}
if (Ctrl)
{
shortcutList.Add("Ctrl");
}
if (Alt)
{
shortcutList.Add("Alt");
}
if (Shift)
{
shortcutList.Add(16); // The Shift key or button.
}
if (Code > 0)
{
switch (Code)
{
// https://learn.microsoft.com/uwp/api/windows.system.virtualkey?view=winrt-20348
case 38: // The Up Arrow key or button.
case 40: // The Down Arrow key or button.
case 37: // The Left Arrow key or button.
case 39: // The Right Arrow key or button.
// case 8: // The Back key or button.
// case 13: // The Enter key or button.
shortcutList.Add(Code);
break;
default:
var localKey = Helper.GetKeyName((uint)Code);
shortcutList.Add(localKey);
break;
}
}
return shortcutList;
}
public bool IsValid()
{
if (IsAccessibleShortcut())
{
return false;
}
return (Alt || Ctrl || Win || Shift) && Code != 0;
}
public bool IsEmpty()
{
return !Alt && !Ctrl && !Win && !Shift && Code == 0;
}
public bool IsAccessibleShortcut()
{
// Shift+Tab and Tab are accessible shortcuts
if ((!Alt && !Ctrl && !Win && Shift && Code == VKTAB)
|| (!Alt && !Ctrl && !Win && !Shift && Code == VKTAB))
{
return true;
}
return false;
}
public static bool TryParseFromCmd(string cmd, out object result)
{
bool win = false, ctrl = false, alt = false, shift = false;
int code = 0;
var parts = cmd.Split('+');
foreach (var part in parts)
{
switch (part.Trim().ToLower(CultureInfo.InvariantCulture))
{
case "win":
win = true;
break;
case "ctrl":
ctrl = true;
break;
case "alt":
alt = true;
break;
case "shift":
shift = true;
break;
default:
if (!TryParseKeyCode(part, out code))
{
result = null;
return false;
}
break;
}
}
result = new HotkeySettings(win, ctrl, alt, shift, code);
return true;
}
private static bool TryParseKeyCode(string key, out int keyCode)
{
// ASCII symbol
if (key.Length == 1 && char.IsLetterOrDigit(key[0]))
{
keyCode = char.ToUpper(key[0], CultureInfo.InvariantCulture);
return true;
}
// VK code
else if (key.Length == 4 && key.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
return int.TryParse(key.AsSpan(2), NumberStyles.HexNumber, null, out keyCode);
}
// Alias
else
{
keyCode = (int)Utilities.Helper.GetKeyValue(key);
return keyCode != 0;
}
}
public bool TryToCmdRepresentable(out string result)
{
result = ToString();
result = result.Replace(" ", null);
return true;
}
}
}
@@ -0,0 +1,91 @@
// 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 PowerToys.Interop;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public delegate void KeyEvent(int key);
public delegate bool IsActive();
public delegate bool FilterAccessibleKeyboardEvents(int key, UIntPtr extraInfo);
public class HotkeySettingsControlHook : IDisposable
{
private const int WmKeyDown = 0x100;
private const int WmKeyUp = 0x101;
private const int WmSysKeyDown = 0x0104;
private const int WmSysKeyUp = 0x0105;
private KeyboardHook _hook;
private KeyEvent _keyDown;
private KeyEvent _keyUp;
private IsActive _isActive;
private bool disposedValue;
private FilterAccessibleKeyboardEvents _filterKeyboardEvent;
public HotkeySettingsControlHook(KeyEvent keyDown, KeyEvent keyUp, IsActive isActive, FilterAccessibleKeyboardEvents filterAccessibleKeyboardEvents)
{
_keyDown = keyDown;
_keyUp = keyUp;
_isActive = isActive;
_filterKeyboardEvent = filterAccessibleKeyboardEvents;
_hook = new KeyboardHook(HotkeySettingsHookCallback, IsActive, FilterKeyboardEvents);
_hook.Start();
}
private bool IsActive()
{
return _isActive();
}
private void HotkeySettingsHookCallback(KeyboardEvent ev)
{
switch (ev.message)
{
case WmKeyDown:
case WmSysKeyDown:
_keyDown(ev.key);
break;
case WmKeyUp:
case WmSysKeyUp:
_keyUp(ev.key);
break;
}
}
private bool FilterKeyboardEvents(KeyboardEvent ev)
{
#pragma warning disable CA2020 // Prevent from behavioral change
return _filterKeyboardEvent(ev.key, (UIntPtr)ev.dwExtraInfo);
#pragma warning restore CA2020 // Prevent from behavioral change
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// Dispose the KeyboardHook object to terminate the hook threads
_hook.Dispose();
}
disposedValue = true;
}
}
public bool GetDisposedState() => disposedValue;
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
@@ -0,0 +1,15 @@
// 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.ComponentModel;
namespace Microsoft.PowerToys.Settings.UI.Library;
public interface IAdvancedPasteAction : INotifyPropertyChanged
{
public bool IsShown { get; }
public IEnumerable<IAdvancedPasteAction> SubActions { get; }
}
@@ -0,0 +1,125 @@
// 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.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
using Settings.UI.Library.Attributes;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ImageResizerProperties
{
public ImageResizerProperties()
{
ImageresizerSelectedSizeIndex = new IntProperty(0);
ImageresizerShrinkOnly = new BoolProperty(false);
ImageresizerReplace = new BoolProperty(false);
ImageresizerIgnoreOrientation = new BoolProperty(true);
ImageresizerJpegQualityLevel = new IntProperty(90);
ImageresizerPngInterlaceOption = new IntProperty();
ImageresizerTiffCompressOption = new IntProperty();
ImageresizerFileName = new StringProperty("%1 (%2)");
ImageresizerSizes = new ImageResizerSizes();
ImageresizerKeepDateModified = new BoolProperty();
ImageresizerFallbackEncoder = new StringProperty(new System.Guid("19e4a5aa-5662-4fc5-a0c0-1758028e1057").ToString());
ImageresizerCustomSize = new ImageResizerCustomSizeProperty(new ImageSize(4, "custom", ResizeFit.Fit, 1024, 640, ResizeUnit.Pixel));
}
public ImageResizerProperties(Func<string, string> resourceLoader)
: this()
{
if (resourceLoader == null)
{
throw new ArgumentNullException(nameof(resourceLoader), "Resource loader is null");
}
ImageresizerSizes = new ImageResizerSizes(new ObservableCollection<ImageSize>()
{
new ImageSize(0, resourceLoader("ImageResizer_DefaultSize_Small"), ResizeFit.Fit, 854, 480, ResizeUnit.Pixel),
new ImageSize(1, resourceLoader("ImageResizer_DefaultSize_Medium"), ResizeFit.Fit, 1366, 768, ResizeUnit.Pixel),
new ImageSize(2, resourceLoader("ImageResizer_DefaultSize_Large"), ResizeFit.Fit, 1920, 1080, ResizeUnit.Pixel),
new ImageSize(3, resourceLoader("ImageResizer_DefaultSize_Phone"), ResizeFit.Fit, 320, 568, ResizeUnit.Pixel),
});
}
[JsonPropertyName("imageresizer_selectedSizeIndex")]
public IntProperty ImageresizerSelectedSizeIndex { get; set; }
[JsonPropertyName("imageresizer_shrinkOnly")]
public BoolProperty ImageresizerShrinkOnly { get; set; }
[JsonPropertyName("imageresizer_replace")]
public BoolProperty ImageresizerReplace { get; set; }
[JsonPropertyName("imageresizer_ignoreOrientation")]
public BoolProperty ImageresizerIgnoreOrientation { get; set; }
[JsonPropertyName("imageresizer_jpegQualityLevel")]
public IntProperty ImageresizerJpegQualityLevel { get; set; }
[JsonPropertyName("imageresizer_pngInterlaceOption")]
public IntProperty ImageresizerPngInterlaceOption { get; set; }
[JsonPropertyName("imageresizer_tiffCompressOption")]
public IntProperty ImageresizerTiffCompressOption { get; set; }
[JsonPropertyName("imageresizer_fileName")]
public StringProperty ImageresizerFileName { get; set; }
[JsonPropertyName("imageresizer_sizes")]
[CmdConfigureIgnoreAttribute]
public ImageResizerSizes ImageresizerSizes { get; set; }
[JsonPropertyName("imageresizer_keepDateModified")]
public BoolProperty ImageresizerKeepDateModified { get; set; }
[JsonPropertyName("imageresizer_fallbackEncoder")]
public StringProperty ImageresizerFallbackEncoder { get; set; }
[JsonPropertyName("imageresizer_customSize")]
[CmdConfigureIgnoreAttribute]
public ImageResizerCustomSizeProperty ImageresizerCustomSize { get; set; }
public string ToJsonString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerProperties);
}
}
public enum ResizeFit
{
Fill = 0,
Fit = 1,
Stretch = 2,
}
public enum ResizeUnit
{
Centimeter = 0,
Inch = 1,
Percent = 2,
Pixel = 3,
}
public enum PngInterlaceOption
{
Default = 0,
On = 1,
Off = 2,
}
public enum TiffCompressOption
{
Default = 0,
None = 1,
Ccitt3 = 2,
Ccitt4 = 3,
Lzw = 4,
Rle = 5,
Zip = 6,
}
}
@@ -0,0 +1,54 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ImageResizerSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "Image Resizer";
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
[JsonPropertyName("properties")]
public ImageResizerProperties Properties { get; set; }
public ImageResizerSettings()
{
Version = "1";
Name = ModuleName;
Properties = new ImageResizerProperties();
}
public ImageResizerSettings(Func<string, string> resourceLoader)
: this()
{
Properties = new ImageResizerProperties(resourceLoader);
}
public override string ToJsonString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerSettings);
}
public string GetModuleName()
{
return Name;
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}
@@ -0,0 +1,133 @@
// 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.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using ManagedCommon;
using Settings.UI.Library.Resources;
namespace Microsoft.PowerToys.Settings.UI.Library;
public partial class ImageSize : INotifyPropertyChanged, IHasId
{
public event PropertyChangedEventHandler PropertyChanged;
private bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
bool changed = !EqualityComparer<T>.Default.Equals(field, value);
if (changed)
{
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AccessibleTextHelper)));
}
return changed;
}
public ImageSize(int id = 0, string name = "", ResizeFit fit = ResizeFit.Fit, double width = 0, double height = 0, ResizeUnit unit = ResizeUnit.Pixel)
{
Id = id;
Name = name;
Fit = fit;
Width = width;
Height = height;
Unit = unit;
}
private int _id;
private string _name = string.Empty;
private ResizeFit _fit;
private double _height;
private double _width;
private ResizeUnit _unit;
public int Id
{
get => _id;
set => SetProperty(ref _id, value);
}
/// <summary>
/// Gets a value indicating whether the <see cref="Height"/> property is used. When false, the
/// <see cref="Width"/> property is used to evenly scale the image in both X and Y dimensions.
/// </summary>
[JsonIgnore]
public bool IsHeightUsed
{
// Height is ignored when using percentage scaling where the aspect ratio is maintained
// (i.e. non-stretch fits). In all other cases, both Width and Height are needed.
get => !(Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch);
}
/// <summary>
/// Gets or sets the name of the image size.
/// Invalid values (null, empty, or whitespace) are silently ignored to maintain the existing name.
/// </summary>
[JsonPropertyName("name")]
public string Name
{
get => _name;
set
{
// Prevent setting empty or null names
if (!string.IsNullOrWhiteSpace(value))
{
SetProperty(ref _name, value);
}
}
}
[JsonPropertyName("fit")]
public ResizeFit Fit
{
get => _fit;
set
{
if (SetProperty(ref _fit, value))
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsHeightUsed)));
}
}
}
[JsonPropertyName("width")]
public double Width
{
get => _width;
set => SetProperty(ref _width, value < 0 || double.IsNaN(value) ? 0 : value);
}
[JsonPropertyName("height")]
public double Height
{
get => _height;
set => SetProperty(ref _height, value < 0 || double.IsNaN(value) ? 0 : value);
}
[JsonPropertyName("unit")]
public ResizeUnit Unit
{
get => _unit;
set
{
if (SetProperty(ref _unit, value))
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsHeightUsed)));
}
}
}
/// <summary>
/// Gets access to all properties for formatting accessibility descriptions.
/// </summary>
[JsonIgnore]
public ImageSize AccessibleTextHelper => this;
public string ToJsonString() => JsonSerializer.Serialize(this);
}
@@ -0,0 +1,19 @@
// 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.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ImagerResizerKeepDateModified
{
[JsonPropertyName("value")]
public bool Value { get; set; }
public ImagerResizerKeepDateModified()
{
Value = false;
}
}
}
@@ -0,0 +1,24 @@
// 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.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ImageResizerCustomSizeProperty
{
[JsonPropertyName("value")]
public ImageSize Value { get; set; }
public ImageResizerCustomSizeProperty()
{
Value = new ImageSize();
}
public ImageResizerCustomSizeProperty(ImageSize value)
{
Value = value;
}
}
}
@@ -0,0 +1,19 @@
// 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.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ImageResizerFallbackEncoder
{
[JsonPropertyName("value")]
public string Value { get; set; }
public ImageResizerFallbackEncoder()
{
Value = string.Empty;
}
}
}
@@ -0,0 +1,40 @@
// 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.ObjectModel;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class ImageResizerSizes
{
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
{
WriteIndented = true,
};
// Suppressing this warning because removing the setter breaks
// deserialization with System.Text.Json. This affects the UI display.
// See: https://github.com/dotnet/runtime/issues/30258
[JsonPropertyName("value")]
public ObservableCollection<ImageSize> Value { get; set; }
public ImageResizerSizes()
{
Value = new ObservableCollection<ImageSize>();
}
public ImageResizerSizes(ObservableCollection<ImageSize> value)
{
Value = value;
}
public string ToJsonString()
{
var options = _serializerOptions;
return JsonSerializer.Serialize(this, options);
}
}
}
@@ -0,0 +1,64 @@
// 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.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
// Represents the configuration property of the settings that store Integer type.
public record IntProperty : ICmdLineRepresentable
{
public IntProperty()
{
Value = 0;
}
public IntProperty(int value)
{
Value = value;
}
// Gets or sets the integer value of the settings configuration.
[JsonPropertyName("value")]
public int Value { get; set; }
public static bool TryParseFromCmd(string cmd, out object result)
{
result = null;
if (!int.TryParse(cmd, out var value))
{
return false;
}
result = new IntProperty { Value = value };
return true;
}
// Returns a JSON version of the class settings configuration class.
public override string ToString()
{
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.IntProperty);
}
public static implicit operator IntProperty(int v)
{
throw new NotImplementedException();
}
public static implicit operator IntProperty(uint v)
{
throw new NotImplementedException();
}
public bool TryToCmdRepresentable(out string result)
{
result = Value.ToString(CultureInfo.InvariantCulture);
return true;
}
}
}
@@ -0,0 +1,126 @@
// 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.Globalization;
using System.Reflection;
namespace Microsoft.PowerToys.Settings.UI.Library;
/// <summary>
/// A helper interface to allow parsing property values from their command line representation.
/// </summary>
public interface ICmdLineRepresentable
{
public static abstract bool TryParseFromCmd(string cmd, out object result);
public abstract bool TryToCmdRepresentable(out string result);
public static sealed bool TryToCmdRepresentableFor(Type type, object value, out string result)
{
result = null;
if (!typeof(ICmdLineRepresentable).IsAssignableFrom(type))
{
throw new ArgumentException($"{type} doesn't implement {nameof(ICmdLineRepresentable)}");
}
var method = type.GetMethod(nameof(TryToCmdRepresentable));
var parameters = new object[] { result };
if ((bool)method.Invoke(value, parameters))
{
result = (string)parameters[0];
return true;
}
return false;
}
public static sealed bool TryParseFromCmdFor(Type type, string cmd, out object result)
{
result = null;
if (!typeof(ICmdLineRepresentable).IsAssignableFrom(type))
{
throw new ArgumentException($"{type} doesn't implement {nameof(ICmdLineRepresentable)}");
}
var method = type.GetMethod(nameof(TryParseFromCmd), BindingFlags.Static | BindingFlags.Public);
var parameters = new object[] { cmd, null };
if ((bool)method.Invoke(null, parameters))
{
result = parameters[1];
return true;
}
return false;
}
public static sealed object ParseFor(Type type, string cmdRepr)
{
if (type.IsEnum)
{
return Enum.Parse(type, cmdRepr);
}
else if (type.IsPrimitive)
{
if (type == typeof(bool))
{
return bool.Parse(cmdRepr.ToLowerInvariant());
}
else
{
// Converts numeric types like Uint32
return Convert.ChangeType(cmdRepr, type, CultureInfo.InvariantCulture);
}
}
else if (type.IsValueType && type == typeof(DateTimeOffset))
{
if (DateTimeOffset.TryParse(cmdRepr, out var structResult))
{
return structResult;
}
throw new ArgumentException($"Invalid DateTimeOffset format '{cmdRepr}'");
}
else if (type.IsClass)
{
if (type == typeof(string))
{
return cmdRepr;
}
else
{
TryParseFromCmdFor(type, cmdRepr, out var classResult);
return classResult;
}
}
throw new NotImplementedException($"Parsing type {type} is not supported yet");
}
public static string ToCmdRepr(Type type, object value)
{
if (type.IsEnum || type.IsPrimitive)
{
return value.ToString();
}
else if (type.IsValueType && type == typeof(DateTimeOffset))
{
return ((DateTimeOffset)value).ToString("o");
}
else if (type.IsClass)
{
if (type == typeof(string))
{
return (string)value;
}
else
{
TryToCmdRepresentableFor(type, value, out var result);
return result;
}
}
throw new NotImplementedException($"CmdRepr of {type} is not supported yet");
}
}
@@ -0,0 +1,17 @@
// 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 ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
namespace Microsoft.PowerToys.Settings.UI.Library.Interfaces
{
public interface IHotkeyConfig
{
HotkeyAccessor[] GetAllHotkeyAccessors();
ModuleType GetModuleType();
}
}
@@ -0,0 +1,16 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.Interfaces
{
// Common interface to be implemented by all the objects which get and store settings properties.
public interface ISettingsConfig
{
string ToJsonString();
string GetModuleName();
bool UpgradeSettingsConfiguration();
}
}
@@ -0,0 +1,17 @@
// 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;
namespace Microsoft.PowerToys.Settings.UI.Library.Interfaces
{
public interface ISettingsRepository<T>
{
T SettingsConfig { get; set; }
bool ReloadSettings();
event Action<T> SettingsChanged;
}
}
@@ -0,0 +1,44 @@
// 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.Globalization;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public record KeyboardKeysProperty : ICmdLineRepresentable
{
public KeyboardKeysProperty()
{
Value = new HotkeySettings();
}
public KeyboardKeysProperty(HotkeySettings hkSettings)
{
Value = hkSettings;
}
[JsonPropertyName("value")]
public HotkeySettings Value { get; set; }
public static bool TryParseFromCmd(string cmd, out object result)
{
if (!HotkeySettings.TryParseFromCmd(cmd, out var hotkey))
{
result = null;
return false;
}
else
{
result = new KeyboardKeysProperty { Value = (HotkeySettings)hotkey };
return true;
}
}
public bool TryToCmdRepresentable(out string result)
{
return Value.TryToCmdRepresentable(out result);
}
}
}

Some files were not shown because too many files have changed in this diff Show More