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 }