diff --git a/lib/libimhex/include/hex/api/content_registry.hpp b/lib/libimhex/include/hex/api/content_registry.hpp index bfb6e5fdf..ff219d354 100644 --- a/lib/libimhex/include/hex/api/content_registry.hpp +++ b/lib/libimhex/include/hex/api/content_registry.hpp @@ -2,10 +2,10 @@ #include #include +#include #include #include -#include #include #include #include @@ -24,7 +24,6 @@ enum ImGuiCustomCol : int; namespace hex { class View; - class Shortcut; class Task; namespace dp { @@ -771,7 +770,7 @@ namespace hex { struct MenuItem { std::vector unlocalizedNames; Icon icon; - std::unique_ptr shortcut; + Shortcut shortcut; View *view; MenuCallback callback; EnabledCallback enabledCallback; diff --git a/lib/libimhex/include/hex/api/shortcut_manager.hpp b/lib/libimhex/include/hex/api/shortcut_manager.hpp index 48cad1993..7354d492c 100644 --- a/lib/libimhex/include/hex/api/shortcut_manager.hpp +++ b/lib/libimhex/include/hex/api/shortcut_manager.hpp @@ -17,7 +17,7 @@ namespace hex { class View; - enum class Keys { + enum class Keys : u32 { Space = GLFW_KEY_SPACE, Apostrophe = GLFW_KEY_APOSTROPHE, Comma = GLFW_KEY_COMMA, @@ -187,187 +187,34 @@ namespace hex { } bool operator<(const Shortcut &other) const { - return m_keys < other.m_keys; + u64 left = 0; + for (const auto &key : m_keys) + left |= key.getKeyCode(); + + u64 right = 0; + for (const auto &key : other.m_keys) + right |= key.getKeyCode(); + + return left < right; } bool operator==(const Shortcut &other) const { - auto thisKeys = m_keys; - auto otherKeys = other.m_keys; + u64 left = 0; + for (const auto &key : m_keys) + left |= key.getKeyCode(); - thisKeys.erase(CurrentView); - thisKeys.erase(AllowWhileTyping); - otherKeys.erase(CurrentView); - otherKeys.erase(AllowWhileTyping); + u64 right = 0; + for (const auto &key : other.m_keys) + right |= key.getKeyCode(); - return thisKeys == otherKeys; + return left == right; } bool isLocal() const { return m_keys.contains(CurrentView); } - std::string toString() const { - std::string result; - - #if defined(OS_MACOS) - constexpr static auto CTRL_NAME = "CTRL"; - constexpr static auto ALT_NAME = "OPT"; - constexpr static auto SHIFT_NAME = "SHIFT"; - constexpr static auto SUPER_NAME = "CMD"; - #else - constexpr static auto CTRL_NAME = "CTRL"; - constexpr static auto ALT_NAME = "ALT"; - constexpr static auto SHIFT_NAME = "SHIFT"; - constexpr static auto SUPER_NAME = "SUPER"; - #endif - - constexpr static auto Concatination = " + "; - - auto keys = m_keys; - if (keys.erase(CTRL) > 0) { - result += CTRL_NAME; - result += Concatination; - } - if (keys.erase(ALT) > 0) { - result += ALT_NAME; - result += Concatination; - } - if (keys.erase(SHIFT) > 0) { - result += SHIFT_NAME; - result += Concatination; - } - if (keys.erase(SUPER) > 0) { - result += SUPER_NAME; - result += Concatination; - } - keys.erase(CurrentView); - - for (const auto &key : keys) { - switch (Keys(key.getKeyCode())) { - case Keys::Space: result += "SPACE"; break; - case Keys::Apostrophe: result += "'"; break; - case Keys::Comma: result += ","; break; - case Keys::Minus: result += "-"; break; - case Keys::Period: result += "."; break; - case Keys::Slash: result += "/"; break; - case Keys::Num0: result += "0"; break; - case Keys::Num1: result += "1"; break; - case Keys::Num2: result += "2"; break; - case Keys::Num3: result += "3"; break; - case Keys::Num4: result += "4"; break; - case Keys::Num5: result += "5"; break; - case Keys::Num6: result += "6"; break; - case Keys::Num7: result += "7"; break; - case Keys::Num8: result += "8"; break; - case Keys::Num9: result += "9"; break; - case Keys::Semicolon: result += ";"; break; - case Keys::Equals: result += "="; break; - case Keys::A: result += "A"; break; - case Keys::B: result += "B"; break; - case Keys::C: result += "C"; break; - case Keys::D: result += "D"; break; - case Keys::E: result += "E"; break; - case Keys::F: result += "F"; break; - case Keys::G: result += "G"; break; - case Keys::H: result += "H"; break; - case Keys::I: result += "I"; break; - case Keys::J: result += "J"; break; - case Keys::K: result += "K"; break; - case Keys::L: result += "L"; break; - case Keys::M: result += "M"; break; - case Keys::N: result += "N"; break; - case Keys::O: result += "O"; break; - case Keys::P: result += "P"; break; - case Keys::Q: result += "Q"; break; - case Keys::R: result += "R"; break; - case Keys::S: result += "S"; break; - case Keys::T: result += "T"; break; - case Keys::U: result += "U"; break; - case Keys::V: result += "V"; break; - case Keys::W: result += "W"; break; - case Keys::X: result += "X"; break; - case Keys::Y: result += "Y"; break; - case Keys::Z: result += "Z"; break; - case Keys::LeftBracket: result += "["; break; - case Keys::Backslash: result += "\\"; break; - case Keys::RightBracket: result += "]"; break; - case Keys::GraveAccent: result += "`"; break; - case Keys::World1: result += "WORLD1"; break; - case Keys::World2: result += "WORLD2"; break; - case Keys::Escape: result += "ESC"; break; - case Keys::Enter: result += "ENTER"; break; - case Keys::Tab: result += "TAB"; break; - case Keys::Backspace: result += "BACKSPACE"; break; - case Keys::Insert: result += "INSERT"; break; - case Keys::Delete: result += "DELETE"; break; - case Keys::Right: result += "RIGHT"; break; - case Keys::Left: result += "LEFT"; break; - case Keys::Down: result += "DOWN"; break; - case Keys::Up: result += "UP"; break; - case Keys::PageUp: result += "PAGEUP"; break; - case Keys::PageDown: result += "PAGEDOWN"; break; - case Keys::Home: result += "HOME"; break; - case Keys::End: result += "END"; break; - case Keys::CapsLock: result += "CAPSLOCK"; break; - case Keys::ScrollLock: result += "SCROLLLOCK"; break; - case Keys::NumLock: result += "NUMLOCK"; break; - case Keys::PrintScreen: result += "PRINTSCREEN"; break; - case Keys::Pause: result += "PAUSE"; break; - case Keys::F1: result += "F1"; break; - case Keys::F2: result += "F2"; break; - case Keys::F3: result += "F3"; break; - case Keys::F4: result += "F4"; break; - case Keys::F5: result += "F5"; break; - case Keys::F6: result += "F6"; break; - case Keys::F7: result += "F7"; break; - case Keys::F8: result += "F8"; break; - case Keys::F9: result += "F9"; break; - case Keys::F10: result += "F10"; break; - case Keys::F11: result += "F11"; break; - case Keys::F12: result += "F12"; break; - case Keys::F13: result += "F13"; break; - case Keys::F14: result += "F14"; break; - case Keys::F15: result += "F15"; break; - case Keys::F16: result += "F16"; break; - case Keys::F17: result += "F17"; break; - case Keys::F18: result += "F18"; break; - case Keys::F19: result += "F19"; break; - case Keys::F20: result += "F20"; break; - case Keys::F21: result += "F21"; break; - case Keys::F22: result += "F22"; break; - case Keys::F23: result += "F23"; break; - case Keys::F24: result += "F24"; break; - case Keys::F25: result += "F25"; break; - case Keys::KeyPad0: result += "KP0"; break; - case Keys::KeyPad1: result += "KP1"; break; - case Keys::KeyPad2: result += "KP2"; break; - case Keys::KeyPad3: result += "KP3"; break; - case Keys::KeyPad4: result += "KP4"; break; - case Keys::KeyPad5: result += "KP5"; break; - case Keys::KeyPad6: result += "KP6"; break; - case Keys::KeyPad7: result += "KP7"; break; - case Keys::KeyPad8: result += "KP8"; break; - case Keys::KeyPad9: result += "KP9"; break; - case Keys::KeyPadDecimal: result += "KPDECIMAL"; break; - case Keys::KeyPadDivide: result += "KPDIVIDE"; break; - case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break; - case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break; - case Keys::KeyPadAdd: result += "KPADD"; break; - case Keys::KeyPadEnter: result += "KPENTER"; break; - case Keys::KeyPadEqual: result += "KPEQUAL"; break; - case Keys::Menu: result += "MENU"; break; - default: - continue; - } - - result += " + "; - } - - if (result.ends_with(" + ")) - result = result.substr(0, result.size() - 3); - - return result; - } + std::string toString() const; const std::set& getKeys() const { return m_keys; } diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index 5962ce894..79bf0800b 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -904,7 +904,7 @@ namespace hex { coloredIcon.color = ImGuiCustomCol_ToolbarGray; impl::s_menuItems->insert({ - priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, std::make_unique(shortcut), view, function, enabledCallback, selectedCallback, -1 } + priority, impl::MenuItem { unlocalizedMainMenuNames, coloredIcon, shortcut, view, function, enabledCallback, selectedCallback, -1 } }); if (shortcut != Shortcut::None) { @@ -931,14 +931,14 @@ namespace hex { unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue); impl::s_menuItems->insert({ - priority, impl::MenuItem { unlocalizedMainMenuNames, icon, std::make_unique(), nullptr, function, enabledCallback, []{ return false; }, -1 } + priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, nullptr, function, enabledCallback, []{ return false; }, -1 } }); } void addMenuItemSeparator(std::vector unlocalizedMainMenuNames, u32 priority) { unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue); impl::s_menuItems->insert({ - priority, impl::MenuItem { unlocalizedMainMenuNames, "", std::make_unique(), nullptr, []{}, []{ return true; }, []{ return false; }, -1 } + priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, nullptr, []{}, []{ return true; }, []{ return false; }, -1 } }); } diff --git a/lib/libimhex/source/api/shortcut_manager.cpp b/lib/libimhex/source/api/shortcut_manager.cpp index 4057124da..968b3de63 100644 --- a/lib/libimhex/source/api/shortcut_manager.cpp +++ b/lib/libimhex/source/api/shortcut_manager.cpp @@ -15,20 +15,187 @@ namespace hex { } + std::string Shortcut::toString() const { + std::string result; + + #if defined(OS_MACOS) + constexpr static auto CTRL_NAME = "⌃"; + constexpr static auto ALT_NAME = "⌥"; + constexpr static auto SHIFT_NAME = "⇧"; + constexpr static auto SUPER_NAME = "⌘"; + constexpr static auto Concatination = " "; + #else + constexpr static auto CTRL_NAME = "CTRL"; + constexpr static auto ALT_NAME = "ALT"; + constexpr static auto SHIFT_NAME = "SHIFT"; + constexpr static auto SUPER_NAME = "SUPER"; + constexpr static auto Concatination = " + "; + #endif + + auto keys = m_keys; + if (keys.erase(CTRL) > 0) { + result += CTRL_NAME; + result += Concatination; + } + if (keys.erase(ALT) > 0) { + result += ALT_NAME; + result += Concatination; + } + if (keys.erase(SHIFT) > 0) { + result += SHIFT_NAME; + result += Concatination; + } + if (keys.erase(SUPER) > 0) { + result += SUPER_NAME; + result += Concatination; + } + keys.erase(CurrentView); + + for (const auto &key : keys) { + switch (Keys(key.getKeyCode())) { + case Keys::Space: result += "⎵"; break; + case Keys::Apostrophe: result += "'"; break; + case Keys::Comma: result += ","; break; + case Keys::Minus: result += "-"; break; + case Keys::Period: result += "."; break; + case Keys::Slash: result += "/"; break; + case Keys::Num0: result += "0"; break; + case Keys::Num1: result += "1"; break; + case Keys::Num2: result += "2"; break; + case Keys::Num3: result += "3"; break; + case Keys::Num4: result += "4"; break; + case Keys::Num5: result += "5"; break; + case Keys::Num6: result += "6"; break; + case Keys::Num7: result += "7"; break; + case Keys::Num8: result += "8"; break; + case Keys::Num9: result += "9"; break; + case Keys::Semicolon: result += ";"; break; + case Keys::Equals: result += "="; break; + case Keys::A: result += "A"; break; + case Keys::B: result += "B"; break; + case Keys::C: result += "C"; break; + case Keys::D: result += "D"; break; + case Keys::E: result += "E"; break; + case Keys::F: result += "F"; break; + case Keys::G: result += "G"; break; + case Keys::H: result += "H"; break; + case Keys::I: result += "I"; break; + case Keys::J: result += "J"; break; + case Keys::K: result += "K"; break; + case Keys::L: result += "L"; break; + case Keys::M: result += "M"; break; + case Keys::N: result += "N"; break; + case Keys::O: result += "O"; break; + case Keys::P: result += "P"; break; + case Keys::Q: result += "Q"; break; + case Keys::R: result += "R"; break; + case Keys::S: result += "S"; break; + case Keys::T: result += "T"; break; + case Keys::U: result += "U"; break; + case Keys::V: result += "V"; break; + case Keys::W: result += "W"; break; + case Keys::X: result += "X"; break; + case Keys::Y: result += "Y"; break; + case Keys::Z: result += "Z"; break; + case Keys::LeftBracket: result += "["; break; + case Keys::Backslash: result += "\\"; break; + case Keys::RightBracket: result += "]"; break; + case Keys::GraveAccent: result += "`"; break; + case Keys::World1: result += "WORLD1"; break; + case Keys::World2: result += "WORLD2"; break; + case Keys::Escape: result += "ESC"; break; + case Keys::Enter: result += "⏎"; break; + case Keys::Tab: result += "⇥"; break; + case Keys::Backspace: result += "⌫"; break; + case Keys::Insert: result += "INSERT"; break; + case Keys::Delete: result += "DELETE"; break; + case Keys::Right: result += "RIGHT"; break; + case Keys::Left: result += "LEFT"; break; + case Keys::Down: result += "DOWN"; break; + case Keys::Up: result += "UP"; break; + case Keys::PageUp: result += "PAGEUP"; break; + case Keys::PageDown: result += "PAGEDOWN"; break; + case Keys::Home: result += "HOME"; break; + case Keys::End: result += "END"; break; + case Keys::CapsLock: result += "⇪"; break; + case Keys::ScrollLock: result += "SCROLLLOCK"; break; + case Keys::NumLock: result += "NUMLOCK"; break; + case Keys::PrintScreen: result += "PRINTSCREEN"; break; + case Keys::Pause: result += "PAUSE"; break; + case Keys::F1: result += "F1"; break; + case Keys::F2: result += "F2"; break; + case Keys::F3: result += "F3"; break; + case Keys::F4: result += "F4"; break; + case Keys::F5: result += "F5"; break; + case Keys::F6: result += "F6"; break; + case Keys::F7: result += "F7"; break; + case Keys::F8: result += "F8"; break; + case Keys::F9: result += "F9"; break; + case Keys::F10: result += "F10"; break; + case Keys::F11: result += "F11"; break; + case Keys::F12: result += "F12"; break; + case Keys::F13: result += "F13"; break; + case Keys::F14: result += "F14"; break; + case Keys::F15: result += "F15"; break; + case Keys::F16: result += "F16"; break; + case Keys::F17: result += "F17"; break; + case Keys::F18: result += "F18"; break; + case Keys::F19: result += "F19"; break; + case Keys::F20: result += "F20"; break; + case Keys::F21: result += "F21"; break; + case Keys::F22: result += "F22"; break; + case Keys::F23: result += "F23"; break; + case Keys::F24: result += "F24"; break; + case Keys::F25: result += "F25"; break; + case Keys::KeyPad0: result += "KP0"; break; + case Keys::KeyPad1: result += "KP1"; break; + case Keys::KeyPad2: result += "KP2"; break; + case Keys::KeyPad3: result += "KP3"; break; + case Keys::KeyPad4: result += "KP4"; break; + case Keys::KeyPad5: result += "KP5"; break; + case Keys::KeyPad6: result += "KP6"; break; + case Keys::KeyPad7: result += "KP7"; break; + case Keys::KeyPad8: result += "KP8"; break; + case Keys::KeyPad9: result += "KP9"; break; + case Keys::KeyPadDecimal: result += "KPDECIMAL"; break; + case Keys::KeyPadDivide: result += "KPDIVIDE"; break; + case Keys::KeyPadMultiply: result += "KPMULTIPLY"; break; + case Keys::KeyPadSubtract: result += "KPSUBTRACT"; break; + case Keys::KeyPadAdd: result += "KPADD"; break; + case Keys::KeyPadEnter: result += "KPENTER"; break; + case Keys::KeyPadEqual: result += "KPEQUAL"; break; + case Keys::Menu: result += "MENU"; break; + default: + continue; + } + + result += " + "; + } + + if (result.ends_with(" + ")) + result = result.substr(0, result.size() - 3); + + return result; + } + void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::vector &unlocalizedName, const std::function &callback) { + log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get()); s_globalShortcuts->insert({ shortcut, { shortcut, unlocalizedName, callback } }); } void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function &callback) { + log::debug("Adding global shortcut {} for {}", shortcut.toString(), unlocalizedName.get()); s_globalShortcuts->insert({ shortcut, { shortcut, { unlocalizedName }, callback } }); } void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::vector &unlocalizedName, const std::function &callback) { + log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.back().get()); view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, unlocalizedName, callback } }); } void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const UnlocalizedString &unlocalizedName, const std::function &callback) { + log::debug("Adding shortcut {} for {}", shortcut.toString(), unlocalizedName.get()); view->m_shortcuts.insert({ shortcut + CurrentView, { shortcut, { unlocalizedName }, callback } }); } @@ -142,9 +309,9 @@ namespace hex { } if (result) { - for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) { - if (menuItem.view == view && *menuItem.shortcut == oldShortcut) { - *menuItem.shortcut = newShortcut; + for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItemsMutable()) { + if (menuItem.view == view && menuItem.shortcut == oldShortcut) { + menuItem.shortcut = newShortcut; break; } } diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index 00f2f234e..c7737eda9 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -638,7 +638,7 @@ namespace hex { // Pass on currently pressed keys to the shortcut handler for (const auto &key : m_pressedKeys) { - ShortcutManager::process(view.get(), io.KeyCtrl, io.KeyAlt, io.KeyShift, io.KeySuper, focused, key); + ShortcutManager::process(view.get(), io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl, io.KeyAlt, io.KeyShift, io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeySuper, focused, key); } ImGui::End(); @@ -648,7 +648,7 @@ namespace hex { // Handle global shortcuts for (const auto &key : m_pressedKeys) { - ShortcutManager::processGlobals(io.KeyCtrl, io.KeyAlt, io.KeyShift, io.KeySuper, key); + ShortcutManager::processGlobals(io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl, io.KeyAlt, io.KeyShift, io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeySuper, key); } m_pressedKeys.clear(); diff --git a/plugins/builtin/source/content/window_decoration.cpp b/plugins/builtin/source/content/window_decoration.cpp index 58406d58f..d017e3fbc 100644 --- a/plugins/builtin/source/content/window_decoration.cpp +++ b/plugins/builtin/source/content/window_decoration.cpp @@ -279,7 +279,7 @@ namespace hex::plugin::builtin { toolbarIndex ] = menuItem; - createNestedMenu(unlocalizedNames | std::views::drop(1), icon.glyph.c_str(), *shortcut, callback, enabledCallback, selectedCallack); + createNestedMenu(unlocalizedNames | std::views::drop(1), icon.glyph.c_str(), shortcut, callback, enabledCallback, selectedCallack); } } @@ -535,7 +535,7 @@ namespace hex::plugin::builtin { const auto &[unlocalizedNames, icon, shortcut, view, callback, enabledCallback, selectedCallback, toolbarIndex] = menuItem; if (ImGui::BeginPopup(unlocalizedNames.front().get().c_str())) { - createNestedMenu({ unlocalizedNames.begin() + 1, unlocalizedNames.end() }, icon.glyph.c_str(), *shortcut, callback, enabledCallback, selectedCallback); + createNestedMenu({ unlocalizedNames.begin() + 1, unlocalizedNames.end() }, icon.glyph.c_str(), shortcut, callback, enabledCallback, selectedCallback); ImGui::EndPopup(); } } diff --git a/plugins/fonts/source/font_loader.cpp b/plugins/fonts/source/font_loader.cpp index 2ac7efb5e..5c98cf13d 100644 --- a/plugins/fonts/source/font_loader.cpp +++ b/plugins/fonts/source/font_loader.cpp @@ -148,6 +148,7 @@ namespace hex::fonts { glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesKorean()); glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesThai()); glyphRangesBuilder.AddRanges(m_fontAtlas->GetGlyphRangesVietnamese()); + glyphRangesBuilder.AddText("⌘⌥⌃⇧⏎⇥⌫⇪"); } m_glyphRange.clear(); diff --git a/plugins/fonts/source/fonts.cpp b/plugins/fonts/source/fonts.cpp index d199525d6..a626756a4 100644 --- a/plugins/fonts/source/fonts.cpp +++ b/plugins/fonts/source/fonts.cpp @@ -26,7 +26,7 @@ namespace hex::fonts { }, { -1_scaled, -1_scaled }); - ImHexApi::Fonts::loadFont("Unifont", romfs::get("fonts/unifont.otf").span(), {}, {}, 0, 16); + ImHexApi::Fonts::loadFont("Unifont", romfs::get("fonts/unifont.otf").span(), { }, {}, 0, 16); } } \ No newline at end of file