GlobalHotkeyConflictManager.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.Linq; 8 9 using Microsoft.PowerToys.Settings.UI.Library; 10 using Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts; 11 12 namespace Microsoft.PowerToys.Settings.UI.Services 13 { 14 public class GlobalHotkeyConflictManager 15 { 16 private readonly Func<string, int> _sendIPCMessage; 17 18 private static GlobalHotkeyConflictManager _instance; 19 private AllHotkeyConflictsData _currentConflicts = new AllHotkeyConflictsData(); 20 21 public static GlobalHotkeyConflictManager Instance => _instance; 22 23 public static void Initialize(Func<string, int> sendIPCMessage) 24 { 25 _instance = new GlobalHotkeyConflictManager(sendIPCMessage); 26 } 27 28 private GlobalHotkeyConflictManager(Func<string, int> sendIPCMessage) 29 { 30 _sendIPCMessage = sendIPCMessage; 31 32 IPCResponseService.AllHotkeyConflictsReceived += OnAllHotkeyConflictsReceived; 33 } 34 35 public event EventHandler<AllHotkeyConflictsEventArgs> ConflictsUpdated; 36 37 public void RequestAllConflicts() 38 { 39 var requestMessage = "{\"get_all_hotkey_conflicts\":{}}"; 40 _sendIPCMessage?.Invoke(requestMessage); 41 } 42 43 private void OnAllHotkeyConflictsReceived(object sender, AllHotkeyConflictsEventArgs e) 44 { 45 _currentConflicts = e.Conflicts; 46 ConflictsUpdated?.Invoke(this, e); 47 } 48 49 public bool HasConflictForHotkey(HotkeySettings hotkey, string moduleName, int hotkeyID) 50 { 51 if (hotkey == null) 52 { 53 return false; 54 } 55 56 var allConflictGroups = _currentConflicts.InAppConflicts.Concat(_currentConflicts.SystemConflicts); 57 58 foreach (var group in allConflictGroups) 59 { 60 if (IsHotkeyMatch(hotkey, group.Hotkey)) 61 { 62 if (!string.IsNullOrEmpty(moduleName) && hotkeyID >= 0) 63 { 64 var selfModule = group.Modules.FirstOrDefault(m => 65 m.ModuleName.Equals(moduleName, StringComparison.OrdinalIgnoreCase) && 66 m.HotkeyID == hotkeyID); 67 68 if (selfModule != null && group.Modules.Count == 1) 69 { 70 return false; 71 } 72 } 73 74 return true; 75 } 76 } 77 78 return false; 79 } 80 81 public HotkeyConflictInfo GetConflictInfo(HotkeySettings hotkey) 82 { 83 if (hotkey == null) 84 { 85 return null; 86 } 87 88 var allConflictGroups = _currentConflicts.InAppConflicts.Concat(_currentConflicts.SystemConflicts); 89 90 foreach (var group in allConflictGroups) 91 { 92 if (IsHotkeyMatch(hotkey, group.Hotkey)) 93 { 94 var conflictModules = group.Modules.Where(m => m != null).ToList(); 95 if (conflictModules.Count != 0) 96 { 97 var firstModule = conflictModules.First(); 98 return new HotkeyConflictInfo 99 { 100 IsSystemConflict = group.IsSystemConflict, 101 ConflictingModuleName = firstModule.ModuleName, 102 ConflictingHotkeyID = firstModule.HotkeyID, 103 AllConflictingModules = conflictModules.Select(m => $"{m.ModuleName}:{m.HotkeyID}").ToList(), 104 }; 105 } 106 } 107 } 108 109 return null; 110 } 111 112 private bool IsHotkeyMatch(HotkeySettings settings, HotkeyData data) 113 { 114 return settings.Win == data.Win && 115 settings.Ctrl == data.Ctrl && 116 settings.Shift == data.Shift && 117 settings.Alt == data.Alt && 118 settings.Code == data.Key; 119 } 120 } 121 }