/ src / settings-ui / Settings.UI / Services / GlobalHotkeyConflictManager.cs
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  }