119 std::vector<ImGuiKey> keys;
120 if (shortcut.empty()) {
125 std::vector<std::string> parts = absl::StrSplit(shortcut,
'+');
126 for (
auto& part : parts) {
128 while (!part.empty() && (part.front() ==
' ' || part.front() ==
'\t')) {
129 part.erase(part.begin());
131 while (!part.empty() && (part.back() ==
' ' || part.back() ==
'\t')) {
138 lower.reserve(part.size());
140 lower.push_back(
static_cast<char>(std::tolower(c)));
143 if (lower ==
"ctrl" || lower ==
"control") {
144 keys.push_back(ImGuiMod_Ctrl);
147 if (lower ==
"cmd" || lower ==
"command") {
154 if (lower ==
"win" || lower ==
"super") {
155 keys.push_back(ImGuiMod_Super);
158 if (lower ==
"alt" || lower ==
"opt" || lower ==
"option") {
159 keys.push_back(ImGuiMod_Alt);
162 if (lower ==
"shift") {
163 keys.push_back(ImGuiMod_Shift);
168 if (lower.size() >= 2 && lower[0] ==
'f') {
171 fnum = std::stoi(lower.substr(1));
175 if (fnum >= 1 && fnum <= 24) {
176 keys.push_back(
static_cast<ImGuiKey
>(ImGuiKey_F1 + (fnum - 1)));
182 if (part.size() == 1) {
184 if (mapped != ImGuiKey_COUNT) {
185 keys.push_back(mapped);
200 const ImGuiIO& io = ImGui::GetIO();
204 int scope_priority = 0;
210 auto better = [](
const Candidate& a,
const Candidate& b) ->
bool {
211 if (a.scope_priority != b.scope_priority)
212 return a.scope_priority > b.scope_priority;
213 if (a.key_count != b.key_count)
214 return a.key_count > b.key_count;
215 if (a.mod_count != b.mod_count)
216 return a.mod_count > b.mod_count;
217 return a.name < b.name;
221 bool have_best =
false;
223 for (
const auto& [name, shortcut] : shortcut_manager.
GetShortcuts()) {
224 if (!shortcut.callback) {
227 if (shortcut.keys.empty()) {
231 const ParsedChord chord = DecomposeChord(shortcut.keys);
232 if (chord.main_keys.empty()) {
237 if (io.WantTextInput && chord.required_mods == 0) {
243 if (!ModsSatisfied(io.KeyMods, chord.required_mods)) {
248 bool chord_pressed =
true;
249 for (
size_t i = 0; i + 1 < chord.main_keys.size(); ++i) {
250 if (!ImGui::IsKeyDown(chord.main_keys[i])) {
251 chord_pressed =
false;
255 if (!chord_pressed) {
258 if (!ImGui::IsKeyPressed(chord.main_keys.back(),
false )) {
263 cand.shortcut = &shortcut;
264 cand.scope_priority = ScopePriority(shortcut.scope);
265 cand.key_count =
static_cast<int>(chord.main_keys.size());
266 cand.mod_count = CountMods(chord.required_mods);
269 if (!have_best || better(cand, best)) {
270 best = std::move(cand);
275 if (have_best && best.shortcut && best.shortcut->callback) {
276 best.shortcut->callback();
298 std::function<
void()> save_callback, std::function<
void()> open_callback,
299 std::function<
void()> close_callback, std::function<
void()> find_callback,
300 std::function<
void()> settings_callback) {
312 if (close_callback) {
322 if (settings_callback) {
332 std::function<
void()> focus_left, std::function<
void()> focus_right,
333 std::function<
void()> focus_up, std::function<
void()> focus_down,
334 std::function<
void()> close_window, std::function<
void()> split_horizontal,
335 std::function<
void()> split_vertical) {
363 if (split_horizontal) {
365 {ImGuiMod_Ctrl, ImGuiKey_W, ImGuiKey_S}, split_horizontal);
369 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)