accelerator_util.cc 3.2 KB

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