107 std::vector<ImGuiKey> keys;
108 if (shortcut.empty()) {
113 std::vector<std::string> parts = absl::StrSplit(shortcut,
'+');
114 for (
auto& part : parts) {
116 while (!part.empty() && (part.front() ==
' ' || part.front() ==
'\t')) {
117 part.erase(part.begin());
119 while (!part.empty() && (part.back() ==
' ' || part.back() ==
'\t')) {
122 if (part.empty())
continue;
125 lower.reserve(part.size());
126 for (
char c : part) lower.push_back(
static_cast<char>(std::tolower(c)));
129 if (lower ==
"ctrl" || lower ==
"control") {
130 keys.push_back(ImGuiMod_Ctrl);
133 if (lower ==
"cmd" || lower ==
"command") {
140 if (lower ==
"win" || lower ==
"super") {
141 keys.push_back(ImGuiMod_Super);
144 if (lower ==
"alt" || lower ==
"opt" || lower ==
"option") {
145 keys.push_back(ImGuiMod_Alt);
148 if (lower ==
"shift") {
149 keys.push_back(ImGuiMod_Shift);
154 if (lower.size() >= 2 && lower[0] ==
'f') {
157 fnum = std::stoi(lower.substr(1));
161 if (fnum >= 1 && fnum <= 24) {
162 keys.push_back(
static_cast<ImGuiKey
>(ImGuiKey_F1 + (fnum - 1)));
168 if (part.size() == 1) {
170 if (mapped != ImGuiKey_COUNT) {
171 keys.push_back(mapped);
186 const ImGuiIO& io = ImGui::GetIO();
190 int scope_priority = 0;
196 auto better = [](
const Candidate& a,
const Candidate& b) ->
bool {
197 if (a.scope_priority != b.scope_priority)
198 return a.scope_priority > b.scope_priority;
199 if (a.key_count != b.key_count)
return a.key_count > b.key_count;
200 if (a.mod_count != b.mod_count)
return a.mod_count > b.mod_count;
201 return a.name < b.name;
205 bool have_best =
false;
207 for (
const auto& [name, shortcut] : shortcut_manager.
GetShortcuts()) {
208 if (!shortcut.callback) {
211 if (shortcut.keys.empty()) {
215 const ParsedChord chord = DecomposeChord(shortcut.keys);
216 if (chord.main_keys.empty()) {
221 if (io.WantTextInput && chord.required_mods == 0) {
227 if (!ModsSatisfied(io.KeyMods, chord.required_mods)) {
232 bool chord_pressed =
true;
233 for (
size_t i = 0; i + 1 < chord.main_keys.size(); ++i) {
234 if (!ImGui::IsKeyDown(chord.main_keys[i])) {
235 chord_pressed =
false;
239 if (!chord_pressed) {
242 if (!ImGui::IsKeyPressed(chord.main_keys.back(),
false )) {
247 cand.shortcut = &shortcut;
248 cand.scope_priority = ScopePriority(shortcut.scope);
249 cand.key_count =
static_cast<int>(chord.main_keys.size());
250 cand.mod_count = CountMods(chord.required_mods);
253 if (!have_best || better(cand, best)) {
254 best = std::move(cand);
259 if (have_best && best.shortcut && best.shortcut->callback) {
260 best.shortcut->callback();
282 std::function<
void()> save_callback, std::function<
void()> open_callback,
283 std::function<
void()> close_callback, std::function<
void()> find_callback,
284 std::function<
void()> settings_callback) {
296 if (close_callback) {
306 if (settings_callback) {
316 std::function<
void()> focus_left, std::function<
void()> focus_right,
317 std::function<
void()> focus_up, std::function<
void()> focus_down,
318 std::function<
void()> close_window, std::function<
void()> split_horizontal,
319 std::function<
void()> split_vertical) {
347 if (split_horizontal) {
349 {ImGuiMod_Ctrl, ImGuiKey_W, ImGuiKey_S}, split_horizontal);
353 if (split_vertical) {
void RegisterWindowNavigationShortcuts(std::function< void()> focus_left, std::function< void()> focus_right, std::function< void()> focus_up, std::function< void()> focus_down, std::function< void()> close_window, std::function< void()> split_horizontal, std::function< void()> split_vertical)