accelerator_util.cc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/ui/accelerator_util.h"
  5. #include <stdio.h>
  6. #include <string>
  7. #include <vector>
  8. #include "base/logging.h"
  9. #include "base/stl_util.h"
  10. #include "base/strings/string_split.h"
  11. #include "base/strings/string_util.h"
  12. #include "shell/common/keyboard_util.h"
  13. namespace accelerator_util {
  14. bool StringToAccelerator(const std::string& shortcut,
  15. ui::Accelerator* accelerator) {
  16. if (!base::IsStringASCII(shortcut)) {
  17. LOG(ERROR) << "The accelerator string can only contain ASCII characters, "
  18. "invalid string: "
  19. << "\"" << shortcut << "\"";
  20. return false;
  21. }
  22. std::vector<std::string> tokens = base::SplitString(
  23. shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  24. // Now, parse it into an accelerator.
  25. int modifiers = ui::EF_NONE;
  26. ui::KeyboardCode key = ui::VKEY_UNKNOWN;
  27. std::optional<char16_t> shifted_char;
  28. for (const auto& token : tokens) {
  29. ui::KeyboardCode code = electron::KeyboardCodeFromStr(token, &shifted_char);
  30. if (shifted_char)
  31. modifiers |= ui::EF_SHIFT_DOWN;
  32. switch (code) {
  33. // The token can be a modifier.
  34. case ui::VKEY_SHIFT:
  35. modifiers |= ui::EF_SHIFT_DOWN;
  36. break;
  37. case ui::VKEY_CONTROL:
  38. modifiers |= ui::EF_CONTROL_DOWN;
  39. break;
  40. case ui::VKEY_MENU:
  41. modifiers |= ui::EF_ALT_DOWN;
  42. break;
  43. case ui::VKEY_COMMAND:
  44. modifiers |= ui::EF_COMMAND_DOWN;
  45. break;
  46. case ui::VKEY_ALTGR:
  47. modifiers |= ui::EF_ALTGR_DOWN;
  48. break;
  49. // Or it is a normal key.
  50. default:
  51. key = code;
  52. }
  53. }
  54. if (key == ui::VKEY_UNKNOWN) {
  55. LOG(WARNING) << shortcut << " doesn't contain a valid key";
  56. return false;
  57. }
  58. *accelerator = ui::Accelerator(key, modifiers);
  59. accelerator->shifted_char = shifted_char;
  60. return true;
  61. }
  62. void GenerateAcceleratorTable(AcceleratorTable* table,
  63. electron::ElectronMenuModel* model) {
  64. size_t count = model->GetItemCount();
  65. for (size_t i = 0; i < count; ++i) {
  66. electron::ElectronMenuModel::ItemType type = model->GetTypeAt(i);
  67. if (type == electron::ElectronMenuModel::TYPE_SUBMENU) {
  68. auto* submodel = model->GetSubmenuModelAt(i);
  69. GenerateAcceleratorTable(table, submodel);
  70. } else {
  71. ui::Accelerator accelerator;
  72. if (model->ShouldRegisterAcceleratorAt(i)) {
  73. if (model->GetAcceleratorAtWithParams(i, true, &accelerator)) {
  74. MenuItem item = {i, model};
  75. (*table)[accelerator] = item;
  76. }
  77. }
  78. }
  79. }
  80. }
  81. bool TriggerAcceleratorTableCommand(AcceleratorTable* table,
  82. const ui::Accelerator& accelerator) {
  83. const auto iter = table->find(accelerator);
  84. if (iter != std::end(*table)) {
  85. const accelerator_util::MenuItem& item = iter->second;
  86. if (item.model->IsEnabledAt(item.position)) {
  87. const auto event_flags =
  88. accelerator.MaskOutKeyEventFlags(accelerator.modifiers());
  89. item.model->ActivatedAt(item.position, event_flags);
  90. return true;
  91. }
  92. }
  93. return false;
  94. }
  95. } // namespace accelerator_util