/ src / runner / centralized_hotkeys.cpp
centralized_hotkeys.cpp
  1  #include "pch.h"
  2  #include "centralized_hotkeys.h"
  3  
  4  #include <map>
  5  #include <common/logger/logger.h>
  6  #include <common/utils/winapi_error.h>
  7  #include <common/SettingsAPI/settings_objects.h>
  8  
  9  namespace CentralizedHotkeys
 10  {
 11      std::map<Shortcut, std::vector<Action>> actions;
 12      std::map<Shortcut, int> ids;
 13      HWND runnerWindow;
 14  
 15      std::wstring ToWstring(const Shortcut& shortcut)
 16      {
 17          std::wstring res = L"";
 18          if (shortcut.modifiersMask & MOD_SHIFT)
 19          {
 20              res += L"shift+";
 21          }
 22  
 23          if (shortcut.modifiersMask & MOD_CONTROL)
 24          {
 25              res += L"ctrl+";
 26          }
 27  
 28          if (shortcut.modifiersMask & MOD_WIN)
 29          {
 30              res += L"win+";
 31          }
 32  
 33          if (shortcut.modifiersMask & MOD_ALT)
 34          {
 35              res += L"alt+";
 36          }
 37  
 38          res += PowerToysSettings::HotkeyObject::key_from_code(shortcut.vkCode);
 39  
 40          return res;
 41      }
 42  
 43      bool AddHotkeyAction(Shortcut shortcut, Action action)
 44      {
 45          if (!actions[shortcut].empty())
 46          {
 47              // It will only work if previous one is rewritten
 48              Logger::warn(L"{} shortcut is already registered", ToWstring(shortcut));
 49          }
 50  
 51          actions[shortcut].push_back(action);
 52          // Register hotkey if it is the first shortcut
 53          if (actions[shortcut].size() == 1)
 54          {
 55              if (ids.find(shortcut) == ids.end())
 56              {
 57                  static int nextId = 0;
 58                  ids[shortcut] = nextId++;
 59              }
 60  
 61              if (!RegisterHotKey(runnerWindow, ids[shortcut], shortcut.modifiersMask, shortcut.vkCode))
 62              {
 63                  Logger::warn(L"Failed to add {} shortcut. {}", ToWstring(shortcut), get_last_error_or_default(GetLastError()));
 64                  return false;
 65              }
 66  
 67              Logger::trace(L"{} shortcut registered", ToWstring(shortcut));
 68              return true;
 69          }
 70  
 71          return true;
 72      }
 73  
 74      void UnregisterHotkeysForModule(std::wstring moduleName)
 75      {
 76          for (auto it = actions.begin(); it != actions.end(); it++)
 77          {
 78              auto val = std::find_if(it->second.begin(), it->second.end(), [moduleName](Action a) { return a.moduleName == moduleName; });
 79              if (val != it->second.end())
 80              {
 81                  it->second.erase(val);
 82  
 83                  if (it->second.empty())
 84                  {
 85                      if (!UnregisterHotKey(runnerWindow, ids[it->first]))
 86                      {
 87                          Logger::warn(L"Failed to unregister {} shortcut. {}", ToWstring(it->first), get_last_error_or_default(GetLastError()));
 88                      }
 89                      else
 90                      {
 91                          Logger::trace(L"{} shortcut unregistered", ToWstring(it->first));
 92                      }
 93                  }
 94              }
 95          }
 96      }
 97  
 98      void PopulateHotkey(Shortcut shortcut)
 99      {
100          if (!actions.empty())
101          {
102              try
103              {
104                  actions[shortcut].begin()->action(shortcut.modifiersMask, shortcut.vkCode);
105              }
106              catch(std::exception& ex)
107              {
108                  Logger::error("Failed to execute hotkey's action. {}", ex.what());
109              }
110              catch(...)
111              {
112                  Logger::error(L"Failed to execute hotkey's action");
113              }
114          }
115      }
116  
117      void RegisterWindow(HWND hwnd)
118      {
119          runnerWindow = hwnd;
120      }
121  }