/ src / modules / keyboardmanager / common / Shortcut.cpp
Shortcut.cpp
  1  #include "pch.h"
  2  #include "Shortcut.h"
  3  #include <common/interop/keyboard_layout.h>
  4  #include <common/interop/shared_constants.h>
  5  #include "Helpers.h"
  6  #include "InputInterface.h"
  7  #include <string>
  8  #include <sstream>
  9  
 10  // Function to split a wstring based on a delimiter and return a vector of split strings
 11  std::vector<std::wstring> Shortcut::splitwstring(const std::wstring& input, wchar_t delimiter)
 12  {
 13      std::wstringstream ss(input);
 14      std::wstring item;
 15      std::vector<std::wstring> splittedStrings;
 16      while (std::getline(ss, item, delimiter))
 17      {
 18          splittedStrings.push_back(item);
 19      }
 20  
 21      return splittedStrings;
 22  }
 23  
 24  // Constructor to initialize Shortcut from its virtual key code string representation.
 25  Shortcut::Shortcut(const std::wstring& shortcutVK) :
 26      winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
 27  {
 28      auto keys = splitwstring(shortcutVK, ';');
 29      SetKeyCodes(ConvertToNumbers(keys));
 30  }
 31  
 32  std::vector<int32_t> Shortcut::ConvertToNumbers(std::vector<std::wstring>& keys)
 33  {
 34      std::vector<int32_t> keysAsNumbers;
 35      for (auto it : keys)
 36      {
 37          auto vkKeyCode = std::stoul(it);
 38          keysAsNumbers.push_back(vkKeyCode);
 39      }
 40      return keysAsNumbers;
 41  }
 42  
 43  // Constructor to initialize Shortcut from single key
 44  Shortcut::Shortcut(const DWORD key)
 45  {
 46      SetKey(key);
 47  }
 48  
 49  // Constructor to initialize Shortcut from its virtual key code string representation.
 50  Shortcut::Shortcut(const std::wstring& shortcutVK, const DWORD secondKeyOfChord) :
 51      winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
 52  {
 53      auto keys = splitwstring(shortcutVK, ';');
 54      SetKeyCodes(ConvertToNumbers(keys));
 55      secondKey = secondKeyOfChord;
 56  }
 57  
 58  // Constructor to initialize shortcut from a list of keys
 59  Shortcut::Shortcut(const std::vector<int32_t>& keys)
 60  {
 61      SetKeyCodes(keys);
 62  }
 63  
 64  // Function to return the number of keys in the shortcut
 65  int Shortcut::Size() const
 66  {
 67      int size = 0;
 68      if (winKey != ModifierKey::Disabled)
 69      {
 70          size += 1;
 71      }
 72      if (ctrlKey != ModifierKey::Disabled)
 73      {
 74          size += 1;
 75      }
 76      if (altKey != ModifierKey::Disabled)
 77      {
 78          size += 1;
 79      }
 80      if (shiftKey != ModifierKey::Disabled)
 81      {
 82          size += 1;
 83      }
 84      if (actionKey != NULL)
 85      {
 86          size += 1;
 87      }
 88  
 89      return size;
 90  }
 91  
 92  // Function to return true if the shortcut has no keys set
 93  bool Shortcut::IsEmpty() const
 94  {
 95      if (winKey == ModifierKey::Disabled && ctrlKey == ModifierKey::Disabled && altKey == ModifierKey::Disabled && shiftKey == ModifierKey::Disabled && actionKey == NULL)
 96      {
 97          return true;
 98      }
 99      else
100      {
101          return false;
102      }
103  }
104  
105  // Function to reset all the keys in the shortcut
106  void Shortcut::Reset()
107  {
108      winKey = ModifierKey::Disabled;
109      ctrlKey = ModifierKey::Disabled;
110      altKey = ModifierKey::Disabled;
111      shiftKey = ModifierKey::Disabled;
112      actionKey = NULL;
113      secondKey = NULL;
114      chordStarted = false;
115  }
116  
117  // Function to return the action key
118  DWORD Shortcut::GetActionKey() const
119  {
120      return actionKey;
121  }
122  
123  bool Shortcut::IsRunProgram() const
124  {
125      return operationType == OperationType::RunProgram;
126  }
127  
128  bool Shortcut::IsOpenURI() const
129  {
130      return operationType == OperationType::OpenURI;
131  }
132  
133  DWORD Shortcut::GetSecondKey() const
134  {
135      return secondKey;
136  }
137  
138  bool Shortcut::HasChord() const
139  {
140      return secondKey != NULL;
141  }
142  
143  void Shortcut::SetChordStarted(bool started)
144  {
145      chordStarted = started;
146  }
147  
148  bool Shortcut::IsChordStarted() const
149  {
150      return chordStarted;
151  }
152  
153  // Function to return the virtual key code of the win key state expected in the shortcut. Argument is used to decide which win key to return in case of both. If the current shortcut doesn't use both win keys then arg is ignored. Return NULL if it is not a part of the shortcut
154  DWORD Shortcut::GetWinKey(const ModifierKey& input) const
155  {
156      if (winKey == ModifierKey::Disabled)
157      {
158          return NULL;
159      }
160      else if (winKey == ModifierKey::Left)
161      {
162          return VK_LWIN;
163      }
164      else if (winKey == ModifierKey::Right)
165      {
166          return VK_RWIN;
167      }
168      else
169      {
170          // Since VK_WIN does not exist if right windows key is to be sent based on the argument, then return VK_RWIN as the win key (since that will be used to release it).
171          if (input == ModifierKey::Right)
172          {
173              return VK_RWIN;
174          }
175          else if (input == ModifierKey::Left || input == ModifierKey::Disabled)
176          {
177              //return VK_LWIN by default
178              return VK_LWIN;
179          }
180          else
181          {
182              return CommonSharedConstants::VK_WIN_BOTH;
183          }
184      }
185  }
186  
187  // Function to return the virtual key code of the ctrl key state expected in the shortcut. Return NULL if it is not a part of the shortcut
188  DWORD Shortcut::GetCtrlKey(const ModifierKey& input) const
189  {
190      if (ctrlKey == ModifierKey::Disabled)
191      {
192          return NULL;
193      }
194      else if (ctrlKey == ModifierKey::Left)
195      {
196          return VK_LCONTROL;
197      }
198      else if (ctrlKey == ModifierKey::Right)
199      {
200          return VK_RCONTROL;
201      }
202      else
203      {
204          if (input == ModifierKey::Right)
205          {
206              return VK_RCONTROL;
207          }
208          if (input == ModifierKey::Left)
209          {
210              return VK_LCONTROL;
211          }
212          return VK_CONTROL;
213      }
214  }
215  
216  // Function to return the virtual key code of the alt key state expected in the shortcut. Return NULL if it is not a part of the shortcut
217  DWORD Shortcut::GetAltKey(const ModifierKey& input) const
218  {
219      if (altKey == ModifierKey::Disabled)
220      {
221          return NULL;
222      }
223      else if (altKey == ModifierKey::Left)
224      {
225          return VK_LMENU;
226      }
227      else if (altKey == ModifierKey::Right)
228      {
229          return VK_RMENU;
230      }
231      if (input == ModifierKey::Right)
232      {
233          return VK_RMENU;
234      }
235      else if (input == ModifierKey::Left || input == ModifierKey::Disabled)
236      {
237          return VK_LMENU;
238      }
239      else
240      {
241          return VK_MENU;
242      }
243  }
244  
245  // Function to return the virtual key code of the shift key state expected in the shortcut. Return NULL if it is not a part of the shortcut
246  DWORD Shortcut::GetShiftKey(const ModifierKey& input) const
247  {
248      if (shiftKey == ModifierKey::Disabled)
249      {
250          return NULL;
251      }
252      else if (shiftKey == ModifierKey::Left)
253      {
254          return VK_LSHIFT;
255      }
256      else if (shiftKey == ModifierKey::Right)
257      {
258          return VK_RSHIFT;
259      }
260      else
261      {
262          if (input == ModifierKey::Right)
263          {
264              return VK_RSHIFT;
265          }
266          if (input == ModifierKey::Left)
267          {
268              return VK_LSHIFT;
269          }
270          return VK_SHIFT;
271      }
272  }
273  
274  // Function to check if the input key matches the win key expected in the shortcut
275  bool Shortcut::CheckWinKey(const DWORD input) const
276  {
277      if (winKey == ModifierKey::Disabled)
278      {
279          return false;
280      }
281      else if (winKey == ModifierKey::Left)
282      {
283          return (VK_LWIN == input);
284      }
285      else if (winKey == ModifierKey::Right)
286      {
287          return (VK_RWIN == input);
288      }
289      // If ModifierKey::Both then return true if either left or right (VK_WIN does not exist)
290      else
291      {
292          return (VK_LWIN == input) || (VK_RWIN == input);
293      }
294  }
295  
296  // Function to check if the input key matches the ctrl key expected in the shortcut
297  bool Shortcut::CheckCtrlKey(const DWORD input) const
298  {
299      if (ctrlKey == ModifierKey::Disabled)
300      {
301          return false;
302      }
303      else if (ctrlKey == ModifierKey::Left)
304      {
305          return (VK_LCONTROL == input);
306      }
307      else if (ctrlKey == ModifierKey::Right)
308      {
309          return (VK_RCONTROL == input);
310      }
311      // If ModifierKey::Both then return true if either left or right or common
312      else
313      {
314          return (VK_CONTROL == input) || (VK_LCONTROL == input) || (VK_RCONTROL == input);
315      }
316  }
317  
318  // Function to check if the input key matches the alt key expected in the shortcut
319  bool Shortcut::CheckAltKey(const DWORD input) const
320  {
321      if (altKey == ModifierKey::Disabled)
322      {
323          return false;
324      }
325      else if (altKey == ModifierKey::Left)
326      {
327          return (VK_LMENU == input);
328      }
329      else if (altKey == ModifierKey::Right)
330      {
331          return (VK_RMENU == input);
332      }
333      // If ModifierKey::Both then return true if either left or right or common
334      else
335      {
336          return (VK_MENU == input) || (VK_LMENU == input) || (VK_RMENU == input);
337      }
338  }
339  
340  // Function to check if the input key matches the shift key expected in the shortcut
341  bool Shortcut::CheckShiftKey(const DWORD input) const
342  {
343      if (shiftKey == ModifierKey::Disabled)
344      {
345          return false;
346      }
347      else if (shiftKey == ModifierKey::Left)
348      {
349          return (VK_LSHIFT == input);
350      }
351      else if (shiftKey == ModifierKey::Right)
352      {
353          return (VK_RSHIFT == input);
354      }
355      // If ModifierKey::Both then return true if either left or right or common
356      else
357      {
358          return (VK_SHIFT == input) || (VK_LSHIFT == input) || (VK_RSHIFT == input);
359      }
360  }
361  
362  bool Shortcut::SetSecondKey(const DWORD input)
363  {
364      if (secondKey == input)
365      {
366          return false;
367      }
368      secondKey = input;
369      return true;
370  }
371  
372  // Function to set a key in the shortcut based on the passed key code argument. Returns false if it is already set to the same value. This can be used to avoid UI refreshing
373  bool Shortcut::SetKey(const DWORD input)
374  {
375      // Since there isn't a key for a common Win key we use the key code defined by us
376      if (input == CommonSharedConstants::VK_WIN_BOTH)
377      {
378          if (winKey == ModifierKey::Both)
379          {
380              return false;
381          }
382          winKey = ModifierKey::Both;
383      }
384      else if (input == VK_LWIN)
385      {
386          if (winKey == ModifierKey::Left)
387          {
388              return false;
389          }
390          winKey = ModifierKey::Left;
391      }
392      else if (input == VK_RWIN)
393      {
394          if (winKey == ModifierKey::Right)
395          {
396              return false;
397          }
398          winKey = ModifierKey::Right;
399      }
400      else if (input == VK_LCONTROL)
401      {
402          if (ctrlKey == ModifierKey::Left)
403          {
404              return false;
405          }
406          ctrlKey = ModifierKey::Left;
407      }
408      else if (input == VK_RCONTROL)
409      {
410          if (ctrlKey == ModifierKey::Right)
411          {
412              return false;
413          }
414          ctrlKey = ModifierKey::Right;
415      }
416      else if (input == VK_CONTROL)
417      {
418          if (ctrlKey == ModifierKey::Both)
419          {
420              return false;
421          }
422          ctrlKey = ModifierKey::Both;
423      }
424      else if (input == VK_LMENU)
425      {
426          if (altKey == ModifierKey::Left)
427          {
428              return false;
429          }
430          altKey = ModifierKey::Left;
431      }
432      else if (input == VK_RMENU)
433      {
434          if (altKey == ModifierKey::Right)
435          {
436              return false;
437          }
438          altKey = ModifierKey::Right;
439      }
440      else if (input == VK_MENU)
441      {
442          if (altKey == ModifierKey::Both)
443          {
444              return false;
445          }
446          altKey = ModifierKey::Both;
447      }
448      else if (input == VK_LSHIFT)
449      {
450          if (shiftKey == ModifierKey::Left)
451          {
452              return false;
453          }
454          shiftKey = ModifierKey::Left;
455      }
456      else if (input == VK_RSHIFT)
457      {
458          if (shiftKey == ModifierKey::Right)
459          {
460              return false;
461          }
462          shiftKey = ModifierKey::Right;
463      }
464      else if (input == VK_SHIFT)
465      {
466          if (shiftKey == ModifierKey::Both)
467          {
468              return false;
469          }
470          shiftKey = ModifierKey::Both;
471      }
472      else
473      {
474          if (actionKey == input)
475          {
476              return false;
477          }
478          actionKey = input;
479      }
480  
481      return true;
482  }
483  
484  // Function to reset the state of a shortcut key based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key.
485  void Shortcut::ResetKey(const DWORD input)
486  {
487      // Since there isn't a key for a common Win key this is handled with a separate argument.
488      if (input == CommonSharedConstants::VK_WIN_BOTH || input == VK_LWIN || input == VK_RWIN)
489      {
490          winKey = ModifierKey::Disabled;
491      }
492      else if (input == VK_LCONTROL || input == VK_RCONTROL || input == VK_CONTROL)
493      {
494          ctrlKey = ModifierKey::Disabled;
495      }
496      else if (input == VK_LMENU || input == VK_RMENU || input == VK_MENU)
497      {
498          altKey = ModifierKey::Disabled;
499      }
500      else if (input == VK_LSHIFT || input == VK_RSHIFT || input == VK_SHIFT)
501      {
502          shiftKey = ModifierKey::Disabled;
503      }
504  
505      // we always want to reset these also, I think for now since this got a little weirder when chords
506      actionKey = {};
507      secondKey = {};
508  }
509  
510  // Function to return the string representation of the shortcut in virtual key codes appended in a string by ";" separator.
511  winrt::hstring Shortcut::ToHstringVK() const
512  {
513      winrt::hstring output;
514      if (winKey != ModifierKey::Disabled)
515      {
516          output = output + winrt::to_hstring(static_cast<unsigned int>(GetWinKey(ModifierKey::Both))) + winrt::to_hstring(L";");
517      }
518      if (ctrlKey != ModifierKey::Disabled)
519      {
520          output = output + winrt::to_hstring(static_cast<unsigned int>(GetCtrlKey(ModifierKey::Both))) + winrt::to_hstring(L";");
521      }
522      if (altKey != ModifierKey::Disabled)
523      {
524          output = output + winrt::to_hstring(static_cast<unsigned int>(GetAltKey(ModifierKey::Both))) + winrt::to_hstring(L";");
525      }
526      if (shiftKey != ModifierKey::Disabled)
527      {
528          output = output + winrt::to_hstring(static_cast<unsigned int>(GetShiftKey(ModifierKey::Both))) + winrt::to_hstring(L";");
529      }
530      if (actionKey != NULL)
531      {
532          output = output + winrt::to_hstring(static_cast<unsigned int>(GetActionKey())) + winrt::to_hstring(L";");
533      }
534  
535      if (secondKey != NULL)
536      {
537          output = output + winrt::to_hstring(static_cast<unsigned int>(GetSecondKey())) + winrt::to_hstring(L";");
538      }
539  
540      if (!output.empty())
541      {
542          output = winrt::hstring(output.c_str(), output.size() - 1);
543      }
544  
545      return output;
546  }
547  
548  // Function to return a vector of key codes in the display order
549  std::vector<DWORD> Shortcut::GetKeyCodes()
550  {
551      std::vector<DWORD> keys;
552      if (winKey != ModifierKey::Disabled)
553      {
554          keys.push_back(GetWinKey(ModifierKey::Both));
555      }
556      if (ctrlKey != ModifierKey::Disabled)
557      {
558          keys.push_back(GetCtrlKey(ModifierKey::Both));
559      }
560      if (altKey != ModifierKey::Disabled)
561      {
562          keys.push_back(GetAltKey(ModifierKey::Both));
563      }
564      if (shiftKey != ModifierKey::Disabled)
565      {
566          keys.push_back(GetShiftKey(ModifierKey::Both));
567      }
568      if (actionKey != NULL)
569      {
570          keys.push_back(actionKey);
571      }
572      return keys;
573  }
574  
575  bool Shortcut::IsActionKey(const DWORD input)
576  {
577      auto shortcut = Shortcut();
578      shortcut.SetKey(input);
579      return (shortcut.actionKey != NULL);
580  }
581  
582  bool Shortcut::IsModifier(const DWORD input)
583  {
584      auto shortcut = Shortcut();
585      shortcut.SetKey(input);
586      return (shortcut.actionKey == NULL);
587  }
588  
589  // Function to set a shortcut from a vector of key codes
590  void Shortcut::SetKeyCodes(const std::vector<int32_t>& keys)
591  {
592      Reset();
593  
594      bool foundActionKey = false;
595      for (int i = 0; i < keys.size(); i++)
596      {
597          if (keys[i] != -1 && keys[i] != 0)
598          {
599              Shortcut tempShortcut = Shortcut(keys[i]);
600  
601              if (!foundActionKey && tempShortcut.actionKey != NULL)
602              {
603                  // last key was an action key, next key is secondKey
604                  foundActionKey = true;
605                  SetKey(keys[i]);
606              }
607              else if (foundActionKey && tempShortcut.actionKey != NULL)
608              {
609                  // already found actionKey, and we found another, add this as the secondKey
610                  secondKey = keys[i];
611              }
612              else
613              {
614                  // just add whatever it is.
615                  SetKey(keys[i]);
616              }
617          }
618      }
619  }
620  
621  // Function to check if all the modifiers in the shortcut have been pressed down
622  bool Shortcut::CheckModifiersKeyboardState(KeyboardManagerInput::InputInterface& ii) const
623  {
624      // Check the win key state
625      if (winKey == ModifierKey::Both)
626      {
627          // Since VK_WIN does not exist, we check both VK_LWIN and VK_RWIN
628          if ((!(ii.GetVirtualKeyState(VK_LWIN))) && (!(ii.GetVirtualKeyState(VK_RWIN))))
629          {
630              return false;
631          }
632      }
633      else if (winKey == ModifierKey::Left)
634      {
635          if (!(ii.GetVirtualKeyState(VK_LWIN)))
636          {
637              return false;
638          }
639      }
640      else if (winKey == ModifierKey::Right)
641      {
642          if (!(ii.GetVirtualKeyState(VK_RWIN)))
643          {
644              return false;
645          }
646      }
647  
648      // Check the ctrl key state
649      if (ctrlKey == ModifierKey::Left)
650      {
651          if (!(ii.GetVirtualKeyState(VK_LCONTROL)))
652          {
653              return false;
654          }
655      }
656      else if (ctrlKey == ModifierKey::Right)
657      {
658          if (!(ii.GetVirtualKeyState(VK_RCONTROL)))
659          {
660              return false;
661          }
662      }
663      else if (ctrlKey == ModifierKey::Both)
664      {
665          if (!(ii.GetVirtualKeyState(VK_CONTROL)))
666          {
667              return false;
668          }
669      }
670  
671      // Check the alt key state
672      if (altKey == ModifierKey::Left)
673      {
674          if (!(ii.GetVirtualKeyState(VK_LMENU)))
675          {
676              return false;
677          }
678      }
679      else if (altKey == ModifierKey::Right)
680      {
681          if (!(ii.GetVirtualKeyState(VK_RMENU)))
682          {
683              return false;
684          }
685      }
686      else if (altKey == ModifierKey::Both)
687      {
688          if (!(ii.GetVirtualKeyState(VK_MENU)))
689          {
690              return false;
691          }
692      }
693  
694      // Check the shift key state
695      if (shiftKey == ModifierKey::Left)
696      {
697          if (!(ii.GetVirtualKeyState(VK_LSHIFT)))
698          {
699              return false;
700          }
701      }
702      else if (shiftKey == ModifierKey::Right)
703      {
704          if (!(ii.GetVirtualKeyState(VK_RSHIFT)))
705          {
706              return false;
707          }
708      }
709      else if (shiftKey == ModifierKey::Both)
710      {
711          if (!(ii.GetVirtualKeyState(VK_SHIFT)))
712          {
713              return false;
714          }
715      }
716  
717      return true;
718  }
719  
720  // Helper method for checking if a key is in a range for cleaner code
721  constexpr bool in_range(DWORD key, DWORD a, DWORD b)
722  {
723      return (key >= a && key <= b);
724  }
725  
726  // Helper method for checking if a key is equal to a value for cleaner code
727  constexpr bool equals(DWORD key, DWORD a)
728  {
729      return (key == a);
730  }
731  
732  // Function to check if the key code is to be ignored
733  bool IgnoreKeyCode(DWORD key)
734  {
735      // Ignore mouse buttons. Keeping this could cause a remapping to fail if a mouse button is also pressed at the same time
736      switch (key)
737      {
738      case VK_LBUTTON:
739      case VK_RBUTTON:
740      case VK_MBUTTON:
741      case VK_XBUTTON1:
742      case VK_XBUTTON2:
743          return true;
744      }
745  
746      // As per docs: https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes
747      // Undefined keys
748      bool isUndefined = equals(key, 0x07) || in_range(key, 0x0E, 0x0F) || in_range(key, 0x3A, 0x40);
749  
750      // Reserved keys
751      bool isReserved = in_range(key, 0x0A, 0x0B) || equals(key, 0x5E) || in_range(key, 0xB8, 0xB9) || in_range(key, 0xC1, 0xD7) || equals(key, 0xE0) || equals(key, VK_NONAME);
752  
753      // Unassigned keys
754      bool isUnassigned = in_range(key, 0x88, 0x8F) || in_range(key, 0x97, 0x9F) || in_range(key, 0xD8, 0xDA) || equals(key, 0xE8);
755  
756      // OEM Specific keys. Ignore these key codes as some of them are used by IME keyboards. More information at https://github.com/microsoft/PowerToys/issues/5225
757      bool isOEMSpecific = in_range(key, 0x92, 0x96) || equals(key, 0xE1) || in_range(key, 0xE3, 0xE4) || equals(key, 0xE6) || in_range(key, 0xE9, 0xF5);
758  
759      // IME keys. Ignore these key codes as some of them are used by IME keyboards. More information at https://github.com/microsoft/PowerToys/issues/6951
760      bool isIME = in_range(key, VK_KANA, 0x1A) || in_range(key, VK_CONVERT, VK_MODECHANGE) || equals(key, VK_PROCESSKEY);
761  
762      if (isUndefined || isReserved || isUnassigned || isOEMSpecific || isIME)
763      {
764          return true;
765      }
766      else
767      {
768          return false;
769      }
770  }
771  
772  // Function to check if any keys are pressed down except those in the shortcut
773  bool Shortcut::IsKeyboardStateClearExceptShortcut(KeyboardManagerInput::InputInterface& ii) const
774  {
775      // Iterate through all the virtual key codes - 0xFF is set to key down because of the Num Lock
776      for (int keyVal = 1; keyVal < 0xFF; keyVal++)
777      {
778          // Ignore problematic key codes
779          if (IgnoreKeyCode(keyVal))
780          {
781              continue;
782          }
783          // Check state of the key. If the key is pressed down but it is not part of the shortcut then the keyboard state is not clear
784          if (ii.GetVirtualKeyState(keyVal))
785          {
786              // If one of the win keys is pressed check if it is part of the shortcut
787              if (keyVal == VK_LWIN)
788              {
789                  if (winKey != ModifierKey::Left && winKey != ModifierKey::Both)
790                  {
791                      return false;
792                  }
793                  else
794                  {
795                      continue;
796                  }
797              }
798              else if (keyVal == VK_RWIN)
799              {
800                  if (winKey != ModifierKey::Right && winKey != ModifierKey::Both)
801                  {
802                      return false;
803                  }
804                  else
805                  {
806                      continue;
807                  }
808              }
809              // If one of the ctrl keys is pressed check if it is part of the shortcut
810              else if (keyVal == VK_LCONTROL)
811              {
812                  if (ctrlKey != ModifierKey::Left && ctrlKey != ModifierKey::Both)
813                  {
814                      return false;
815                  }
816                  else
817                  {
818                      continue;
819                  }
820              }
821              else if (keyVal == VK_RCONTROL)
822              {
823                  if (ctrlKey != ModifierKey::Right && ctrlKey != ModifierKey::Both)
824                  {
825                      return false;
826                  }
827                  else
828                  {
829                      continue;
830                  }
831              }
832              else if (keyVal == VK_CONTROL)
833              {
834                  if (ctrlKey == ModifierKey::Disabled)
835                  {
836                      return false;
837                  }
838                  else
839                  {
840                      continue;
841                  }
842              }
843              // If one of the alt keys is pressed check if it is part of the shortcut
844              else if (keyVal == VK_LMENU)
845              {
846                  if (altKey != ModifierKey::Left && altKey != ModifierKey::Both)
847                  {
848                      return false;
849                  }
850                  else
851                  {
852                      continue;
853                  }
854              }
855              else if (keyVal == VK_RMENU)
856              {
857                  if (altKey != ModifierKey::Right && altKey != ModifierKey::Both)
858                  {
859                      return false;
860                  }
861                  else
862                  {
863                      continue;
864                  }
865              }
866              else if (keyVal == VK_MENU)
867              {
868                  if (altKey == ModifierKey::Disabled)
869                  {
870                      return false;
871                  }
872                  else
873                  {
874                      continue;
875                  }
876              }
877              // If one of the shift keys is pressed check if it is part of the shortcut
878              else if (keyVal == VK_LSHIFT)
879              {
880                  if (shiftKey != ModifierKey::Left && shiftKey != ModifierKey::Both)
881                  {
882                      return false;
883                  }
884                  else
885                  {
886                      continue;
887                  }
888              }
889              else if (keyVal == VK_RSHIFT)
890              {
891                  if (shiftKey != ModifierKey::Right && shiftKey != ModifierKey::Both)
892                  {
893                      return false;
894                  }
895                  else
896                  {
897                      continue;
898                  }
899              }
900              else if (keyVal == VK_SHIFT)
901              {
902                  if (shiftKey == ModifierKey::Disabled)
903                  {
904                      return false;
905                  }
906                  else
907                  {
908                      continue;
909                  }
910              }
911              // If any other key is pressed check if it is the action key
912              else if (keyVal != static_cast<int>(actionKey))
913              {
914                  return false;
915              }
916          }
917      }
918  
919      return true;
920  }
921  
922  // Function to get the number of modifiers that are common between the current shortcut and the shortcut in the argument
923  int Shortcut::GetCommonModifiersCount(const Shortcut& input) const
924  {
925      int commonElements = 0;
926      if ((winKey == input.winKey) && winKey != ModifierKey::Disabled)
927      {
928          commonElements += 1;
929      }
930      if ((ctrlKey == input.ctrlKey) && ctrlKey != ModifierKey::Disabled)
931      {
932          commonElements += 1;
933      }
934      if ((altKey == input.altKey) && altKey != ModifierKey::Disabled)
935      {
936          commonElements += 1;
937      }
938      if ((shiftKey == input.shiftKey) && shiftKey != ModifierKey::Disabled)
939      {
940          commonElements += 1;
941      }
942  
943      return commonElements;
944  }