// 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 ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Views;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
///
/// Static helper class to manage and check hotkey conflict ignore settings
///
public static class HotkeyConflictIgnoreHelper
{
private static readonly ISettingsRepository _generalSettingsRepository;
private static readonly SettingsUtils _settingsUtils;
static HotkeyConflictIgnoreHelper()
{
_settingsUtils = SettingsUtils.Default;
_generalSettingsRepository = SettingsRepository.GetInstance(_settingsUtils);
}
///
/// Ensures ignored conflict properties are initialized
///
private static void EnsureInitialized()
{
var settings = _generalSettingsRepository.SettingsConfig;
if (settings.IgnoredConflictProperties == null)
{
settings.IgnoredConflictProperties = new ShortcutConflictProperties();
SaveSettings();
}
}
///
/// Checks if a specific hotkey setting is configured to ignore conflicts
///
/// The hotkey settings to check
/// True if the hotkey is set to ignore conflicts, false otherwise
public static bool IsIgnoringConflicts(HotkeySettings hotkeySettings)
{
if (hotkeySettings == null)
{
return false;
}
try
{
EnsureInitialized();
var settings = _generalSettingsRepository.SettingsConfig;
return settings.IgnoredConflictProperties.IgnoredShortcuts
.Any(h => AreHotkeySettingsEqual(h, hotkeySettings));
}
catch (Exception ex)
{
Logger.LogError($"Error checking if hotkey is ignoring conflicts: {ex.Message}");
return false;
}
}
///
/// Adds a hotkey setting to the ignored shortcuts list
///
/// The hotkey settings to add to the ignored list
/// True if successfully added, false if it was already ignored or on error
public static bool AddToIgnoredList(HotkeySettings hotkeySettings)
{
if (hotkeySettings == null)
{
return false;
}
try
{
EnsureInitialized();
var settings = _generalSettingsRepository.SettingsConfig;
// Check if already ignored (avoid duplicates)
if (IsIgnoringConflicts(hotkeySettings))
{
Logger.LogInfo($"Hotkey already in ignored list: {hotkeySettings}");
return false;
}
// Add to ignored list
settings.IgnoredConflictProperties.IgnoredShortcuts.Add(hotkeySettings);
SaveSettings();
Logger.LogInfo($"Added hotkey to ignored list: {hotkeySettings}");
return true;
}
catch (Exception ex)
{
Logger.LogError($"Error adding hotkey to ignored list: {ex.Message}");
return false;
}
}
///
/// Removes a hotkey setting from the ignored shortcuts list
///
/// The hotkey settings to remove from the ignored list
/// True if successfully removed, false if it wasn't in the list or on error
public static bool RemoveFromIgnoredList(HotkeySettings hotkeySettings)
{
if (hotkeySettings == null)
{
return false;
}
try
{
EnsureInitialized();
var settings = _generalSettingsRepository.SettingsConfig;
var ignoredShortcut = settings.IgnoredConflictProperties.IgnoredShortcuts
.FirstOrDefault(h => AreHotkeySettingsEqual(h, hotkeySettings));
if (ignoredShortcut != null)
{
settings.IgnoredConflictProperties.IgnoredShortcuts.Remove(ignoredShortcut);
SaveSettings();
Logger.LogInfo($"Removed hotkey from ignored list: {ignoredShortcut}");
return true;
}
Logger.LogInfo($"Hotkey not found in ignored list: {hotkeySettings}");
return false;
}
catch (Exception ex)
{
Logger.LogError($"Error removing hotkey from ignored list: {ex.Message}");
return false;
}
}
///
/// Gets all hotkey settings that are currently being ignored
///
/// List of ignored hotkey settings
public static List GetAllIgnoredShortcuts()
{
try
{
EnsureInitialized();
var settings = _generalSettingsRepository.SettingsConfig;
return new List(settings.IgnoredConflictProperties.IgnoredShortcuts);
}
catch (Exception ex)
{
Logger.LogError($"Error getting ignored shortcuts: {ex.Message}");
return new List();
}
}
///
/// Clears all ignored shortcuts from the list
///
/// True if successfully cleared, false on error
public static bool ClearAllIgnoredShortcuts()
{
try
{
EnsureInitialized();
var settings = _generalSettingsRepository.SettingsConfig;
var count = settings.IgnoredConflictProperties.IgnoredShortcuts.Count;
settings.IgnoredConflictProperties.IgnoredShortcuts.Clear();
SaveSettings();
Logger.LogInfo($"Cleared all {count} ignored shortcuts");
return true;
}
catch (Exception ex)
{
Logger.LogError($"Error clearing ignored shortcuts: {ex.Message}");
return false;
}
}
///
/// Compares two HotkeySettings for equality
///
/// First hotkey settings
/// Second hotkey settings
/// True if they represent the same shortcut, false otherwise
private static bool AreHotkeySettingsEqual(HotkeySettings hotkey1, HotkeySettings hotkey2)
{
if (hotkey1 == null || hotkey2 == null)
{
return false;
}
return hotkey1.Win == hotkey2.Win &&
hotkey1.Ctrl == hotkey2.Ctrl &&
hotkey1.Alt == hotkey2.Alt &&
hotkey1.Shift == hotkey2.Shift &&
hotkey1.Code == hotkey2.Code;
}
///
/// Saves the general settings using PowerToys standard settings persistence
///
private static void SaveSettings()
{
try
{
var settings = _generalSettingsRepository.SettingsConfig;
// Send IPC message to notify runner of changes (this is thread-safe)
var outgoing = new OutGoingGeneralSettings(settings);
ShellPage.SendDefaultIPCMessage(outgoing.ToString());
ShellPage.ShellHandler?.SignalGeneralDataUpdate();
}
catch (Exception ex)
{
Logger.LogError($"Error saving shortcut conflict settings: {ex.Message}");
Logger.LogError($"Stack trace: {ex.StackTrace}");
throw;
}
}
}
}