diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 2f83611bd..f987939bb 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -5,6 +5,7 @@ + diff --git a/include/window.hpp b/include/window.hpp index ea45b9757..596bbe4f1 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -68,6 +68,7 @@ namespace hex { std::filesystem::path m_safetyBackupPath; std::list m_popupsToOpen; + std::vector m_pressedKeys; }; } \ No newline at end of file diff --git a/plugins/builtin/include/content/views/view_command_palette.hpp b/plugins/builtin/include/content/views/view_command_palette.hpp index 15121cdd8..534c1dda3 100644 --- a/plugins/builtin/include/content/views/view_command_palette.hpp +++ b/plugins/builtin/include/content/views/view_command_palette.hpp @@ -23,8 +23,6 @@ namespace hex::plugin::builtin { bool isAvailable() override { return true; } bool shouldProcess() override { return true; } - bool handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt) override; - bool hasViewMenuItemEntry() override { return false; } ImVec2 getMinSize() override { return ImVec2(400, 100); } ImVec2 getMaxSize() override { return ImVec2(400, 100); } diff --git a/plugins/builtin/include/content/views/view_hexeditor.hpp b/plugins/builtin/include/content/views/view_hexeditor.hpp index 448235bed..e6ea73bff 100644 --- a/plugins/builtin/include/content/views/view_hexeditor.hpp +++ b/plugins/builtin/include/content/views/view_hexeditor.hpp @@ -26,7 +26,6 @@ namespace hex::plugin::builtin { void drawContent() override; void drawAlwaysVisible() override; void drawMenu() override; - bool handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt) override; private: MemoryEditor m_memoryEditor; @@ -72,6 +71,8 @@ namespace hex::plugin::builtin { void copyHexView() const; void copyHexViewHTML() const; + void registerEvents(); + void registerShortcuts(); }; } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_command_palette.cpp b/plugins/builtin/source/content/views/view_command_palette.cpp index 765a94c9b..6d0351acc 100644 --- a/plugins/builtin/source/content/views/view_command_palette.cpp +++ b/plugins/builtin/source/content/views/view_command_palette.cpp @@ -6,6 +6,12 @@ namespace hex::plugin::builtin { ViewCommandPalette::ViewCommandPalette() : View("hex.builtin.view.command_palette.name") { this->m_commandBuffer.resize(1024, 0x00); + + ShortcutManager::addGlobalShortcut(CTRL + SHIFT + Keys::P, [this] { + EventManager::post("hex.builtin.view.command_palette.name"_lang); + this->m_commandPaletteOpen = true; + this->m_justOpened = true; + }); } ViewCommandPalette::~ViewCommandPalette() { @@ -72,19 +78,6 @@ namespace hex::plugin::builtin { } - bool ViewCommandPalette::handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt) { - if (ctrl && shift && keys['P']) { - View::doLater([this] { - ImGui::OpenPopup("hex.builtin.view.command_palette.name"_lang); - this->m_commandPaletteOpen = true; - this->m_justOpened = true; - }); - return true; - } - - return false; - } - std::vector ViewCommandPalette::getCommandResults(const std::string &input) { constexpr auto MatchCommand = [](const std::string &currCommand, const std::string &commandToMatch) -> std::pair { if (currCommand.empty()) { diff --git a/plugins/builtin/source/content/views/view_hexeditor.cpp b/plugins/builtin/source/content/views/view_hexeditor.cpp index 0933b0be9..c77e3b6f1 100644 --- a/plugins/builtin/source/content/views/view_hexeditor.cpp +++ b/plugins/builtin/source/content/views/view_hexeditor.cpp @@ -141,134 +141,8 @@ namespace hex::plugin::builtin { return { std::string(decoded), advance, color }; }; - EventManager::subscribe(this, [this](const std::string &filePath) { - this->openFile(filePath); - this->getWindowOpenState() = true; - }); - - EventManager::subscribe(this, [this](Region region) { - auto provider = ImHexApi::Provider::get(); - auto page = provider->getPageOfAddress(region.address); - - if (!page.has_value()) - return; - - if (region.size != 0) { - provider->setCurrentPage(page.value()); - u64 start = region.address - provider->getBaseAddress() - provider->getCurrentPageAddress(); - this->m_memoryEditor.GotoAddrAndSelect(start, start + region.size - 1); - } - - EventManager::post(Region { this->m_memoryEditor.DataPreviewAddr, (this->m_memoryEditor.DataPreviewAddrEnd - this->m_memoryEditor.DataPreviewAddr) + 1}); - }); - - EventManager::subscribe(this, []() { - EventManager::post(ProjectFile::getFilePath()); - }); - - EventManager::subscribe(this, [](GLFWwindow *window) { - if (ProjectFile::hasUnsavedChanges()) { - glfwSetWindowShouldClose(window, GLFW_FALSE); - View::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.exit_application.title"_lang); }); - } - }); - - EventManager::subscribe(this, [this]() { - this->m_highlightedBytes.clear(); - - for (const auto &pattern : SharedData::patternData) { - this->m_highlightedBytes.merge(pattern->getHighlightedAddresses()); - } - }); - - EventManager::subscribe(this, [this](std::string name) { - if (name == "Create File") { - hex::openFileBrowser("hex.builtin.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) { - if (!this->createFile(path)) { - View::showErrorPopup("hex.builtin.view.hexeditor.error.create"_lang); - return; - } - - EventManager::post(path); - this->getWindowOpenState() = true; - }); - } else if (name == "Open File") { - hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) { - EventManager::post(path); - this->getWindowOpenState() = true; - }); - } else if (name == "Open Project") { - hex::openFileBrowser("hex.builtin.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) { - ProjectFile::load(path); - this->getWindowOpenState() = true; - }); - } - }); - - EventManager::subscribe(this, [this] { - { - auto alpha = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.highlight_alpha"); - - if (alpha.is_number()) - this->m_highlightAlpha = alpha; - } - - { - auto columnCount = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.column_count"); - - if (columnCount.is_number()) - this->m_memoryEditor.Cols = static_cast(columnCount); - } - - { - auto hexii = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.hexii"); - - if (hexii.is_number()) - this->m_memoryEditor.OptShowHexII = static_cast(hexii); - } - - { - auto ascii = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.ascii"); - - if (ascii.is_number()) - this->m_memoryEditor.OptShowAscii = static_cast(ascii); - } - - { - auto advancedDecoding = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.advanced_decoding"); - - if (advancedDecoding.is_number()) - this->m_memoryEditor.OptShowAdvancedDecoding = static_cast(advancedDecoding); - } - - { - auto greyOutZeros = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.grey_zeros"); - - if (greyOutZeros.is_number()) - this->m_memoryEditor.OptGreyOutZeroes = static_cast(greyOutZeros); - } - - { - auto upperCaseHex = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.uppercase_hex"); - - if (upperCaseHex.is_number()) - this->m_memoryEditor.OptUpperCaseHex = static_cast(upperCaseHex); - } - - { - auto showExtraInfo = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.extra_info"); - - if (showExtraInfo.is_number()) - this->m_memoryEditor.OptShowExtraInfo = static_cast(showExtraInfo); - } - }); - - EventManager::subscribe(this, [this](auto ®ion) { - u64 address = std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd); - size_t size = std::abs(s64(this->m_memoryEditor.DataPreviewAddrEnd) - s64(this->m_memoryEditor.DataPreviewAddr)) + 1; - - region = Region { address, size }; - }); + registerEvents(); + registerShortcuts(); } ViewHexEditor::~ViewHexEditor() { @@ -635,57 +509,6 @@ namespace hex::plugin::builtin { } } - bool ViewHexEditor::handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt) { - if (ctrl && shift && keys['S']) { - saveAs(); - return true; - } else if (ctrl && keys['S']) { - save(); - return true; - } - - ON_SCOPE_EXIT { ImGui::End(); }; - if (ImGui::Begin(View::toWindowName("hex.builtin.view.hexeditor.name").c_str())) { - - if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) { - if (ctrl && keys['Z']) { - if (ImHexApi::Provider::isValid()) - ImHexApi::Provider::get()->undo(); - return true; - } else if (ctrl && keys['Y']) { - if (ImHexApi::Provider::isValid()) - ImHexApi::Provider::get()->redo(); - } else if (ctrl && keys['F']) { - ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.search"_lang); - return true; - } else if (ctrl && keys['G']) { - ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.goto"_lang); - return true; - } else if (ctrl && keys['O']) { - hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [](auto path) { - EventManager::post(path); - }); - return true; - } else if (ctrl && keys['C']) { - this->copyBytes(); - return true; - } else if (ctrl && shift && keys['C']) { - this->copyString(); - return true; - } else if (ctrl && keys['V']) { - this->pasteBytes(); - return true; - } else if (ctrl && keys['A']) { - auto provider = ImHexApi::Provider::get(); - EventManager::post(Region { provider->getBaseAddress(), provider->getActualSize() }); - return true; - } - } - } - - return false; - } - bool ViewHexEditor::createFile(const std::string &path) { #if defined(OS_WINDOWS) std::wstring widePath; @@ -1361,4 +1184,190 @@ R"( } } + void ViewHexEditor::registerEvents() { + EventManager::subscribe(this, [this](const std::string &filePath) { + this->openFile(filePath); + this->getWindowOpenState() = true; + }); + + EventManager::subscribe(this, [this](Region region) { + auto provider = ImHexApi::Provider::get(); + auto page = provider->getPageOfAddress(region.address); + + if (!page.has_value()) + return; + + if (region.size != 0) { + provider->setCurrentPage(page.value()); + u64 start = region.address - provider->getBaseAddress() - provider->getCurrentPageAddress(); + this->m_memoryEditor.GotoAddrAndSelect(start, start + region.size - 1); + } + + EventManager::post(Region { this->m_memoryEditor.DataPreviewAddr, (this->m_memoryEditor.DataPreviewAddrEnd - this->m_memoryEditor.DataPreviewAddr) + 1}); + }); + + EventManager::subscribe(this, []() { + EventManager::post(ProjectFile::getFilePath()); + }); + + EventManager::subscribe(this, [](GLFWwindow *window) { + if (ProjectFile::hasUnsavedChanges()) { + glfwSetWindowShouldClose(window, GLFW_FALSE); + View::doLater([] { ImGui::OpenPopup("hex.builtin.view.hexeditor.exit_application.title"_lang); }); + } + }); + + EventManager::subscribe(this, [this]() { + this->m_highlightedBytes.clear(); + + for (const auto &pattern : SharedData::patternData) { + this->m_highlightedBytes.merge(pattern->getHighlightedAddresses()); + } + }); + + EventManager::subscribe(this, [this](std::string name) { + if (name == "Create File") { + hex::openFileBrowser("hex.builtin.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) { + if (!this->createFile(path)) { + View::showErrorPopup("hex.builtin.view.hexeditor.error.create"_lang); + return; + } + + EventManager::post(path); + this->getWindowOpenState() = true; + }); + } else if (name == "Open File") { + hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) { + EventManager::post(path); + this->getWindowOpenState() = true; + }); + } else if (name == "Open Project") { + hex::openFileBrowser("hex.builtin.view.hexeditor.open_project"_lang, DialogMode::Open, { { "Project File", "hexproj" } }, [this](auto path) { + ProjectFile::load(path); + this->getWindowOpenState() = true; + }); + } + }); + + EventManager::subscribe(this, [this] { + { + auto alpha = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.highlight_alpha"); + + if (alpha.is_number()) + this->m_highlightAlpha = alpha; + } + + { + auto columnCount = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.column_count"); + + if (columnCount.is_number()) + this->m_memoryEditor.Cols = static_cast(columnCount); + } + + { + auto hexii = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.hexii"); + + if (hexii.is_number()) + this->m_memoryEditor.OptShowHexII = static_cast(hexii); + } + + { + auto ascii = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.ascii"); + + if (ascii.is_number()) + this->m_memoryEditor.OptShowAscii = static_cast(ascii); + } + + { + auto advancedDecoding = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.advanced_decoding"); + + if (advancedDecoding.is_number()) + this->m_memoryEditor.OptShowAdvancedDecoding = static_cast(advancedDecoding); + } + + { + auto greyOutZeros = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.grey_zeros"); + + if (greyOutZeros.is_number()) + this->m_memoryEditor.OptGreyOutZeroes = static_cast(greyOutZeros); + } + + { + auto upperCaseHex = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.uppercase_hex"); + + if (upperCaseHex.is_number()) + this->m_memoryEditor.OptUpperCaseHex = static_cast(upperCaseHex); + } + + { + auto showExtraInfo = ContentRegistry::Settings::getSetting("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.extra_info"); + + if (showExtraInfo.is_number()) + this->m_memoryEditor.OptShowExtraInfo = static_cast(showExtraInfo); + } + }); + + EventManager::subscribe(this, [this](auto ®ion) { + u64 address = std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd); + size_t size = std::abs(s64(this->m_memoryEditor.DataPreviewAddrEnd) - s64(this->m_memoryEditor.DataPreviewAddr)) + 1; + + region = Region { address, size }; + }); + } + + void ViewHexEditor::registerShortcuts() { + ShortcutManager::addGlobalShortcut(CTRL + Keys::S, [] { + save(); + }); + + ShortcutManager::addGlobalShortcut(CTRL + SHIFT + Keys::S, [] { + saveAs(); + }); + + + ShortcutManager::addShortcut(this, CTRL + Keys::Z, [] { + if (ImHexApi::Provider::isValid()) + ImHexApi::Provider::get()->undo(); + }); + + ShortcutManager::addShortcut(this, CTRL + Keys::Y, [] { + if (ImHexApi::Provider::isValid()) + ImHexApi::Provider::get()->redo(); + }); + + + ShortcutManager::addShortcut(this, CTRL + Keys::F, [] { + ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.search"_lang); + }); + + ShortcutManager::addShortcut(this, CTRL + Keys::G, [] { + ImGui::OpenPopupInWindow(View::toWindowName("hex.builtin.view.hexeditor.name").c_str(), "hex.builtin.view.hexeditor.menu.file.goto"_lang); + }); + + ShortcutManager::addShortcut(this, CTRL + Keys::O, [] { + hex::openFileBrowser("hex.builtin.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [](auto path) { + EventManager::post(path); + }); + }); + + + ShortcutManager::addShortcut(this, CTRL + Keys::C, [this] { + this->copyBytes(); + }); + + ShortcutManager::addShortcut(this, CTRL + SHIFT + Keys::C, [this] { + this->copyString(); + }); + + ShortcutManager::addShortcut(this, CTRL + Keys::V, [this] { + this->pasteBytes(); + }); + + ShortcutManager::addShortcut(this, CTRL + Keys::A, [this] { + auto provider = ImHexApi::Provider::get(); + EventManager::post(Region { provider->getBaseAddress(), provider->getActualSize() }); + }); + + } + } \ No newline at end of file diff --git a/plugins/builtin/source/plugin_builtin.cpp b/plugins/builtin/source/plugin_builtin.cpp index 5a3b69f2a..950a8db6f 100644 --- a/plugins/builtin/source/plugin_builtin.cpp +++ b/plugins/builtin/source/plugin_builtin.cpp @@ -1,5 +1,7 @@ #include +#include + namespace hex::plugin::builtin { void registerViews(); diff --git a/plugins/libimhex/CMakeLists.txt b/plugins/libimhex/CMakeLists.txt index a952c53e9..dee134bb5 100644 --- a/plugins/libimhex/CMakeLists.txt +++ b/plugins/libimhex/CMakeLists.txt @@ -104,6 +104,7 @@ set(LIBIMHEX_SOURCES source/api/imhex_api.cpp source/api/content_registry.cpp source/api/task.cpp + source/api/keybinding.cpp source/data_processor/attribute.cpp source/data_processor/link.cpp @@ -134,8 +135,7 @@ set(LIBIMHEX_SOURCES source/providers/provider.cpp source/views/view.cpp - - ) +) if (APPLE) set(OSX_11_0_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk) diff --git a/plugins/libimhex/include/hex/api/imhex_api.hpp b/plugins/libimhex/include/hex/api/imhex_api.hpp index d763be2fb..bfd543a7b 100644 --- a/plugins/libimhex/include/hex/api/imhex_api.hpp +++ b/plugins/libimhex/include/hex/api/imhex_api.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace hex { diff --git a/plugins/libimhex/include/hex/api/keybinding.hpp b/plugins/libimhex/include/hex/api/keybinding.hpp new file mode 100644 index 000000000..de667f46f --- /dev/null +++ b/plugins/libimhex/include/hex/api/keybinding.hpp @@ -0,0 +1,184 @@ +#pragma once + +#include +#include + +#include +#include +#include + +struct ImGuiWindow; + +namespace hex { + + struct View; + + enum class Keys { + Space = GLFW_KEY_SPACE, + Apostrophe = GLFW_KEY_APOSTROPHE, + Comma = GLFW_KEY_COMMA, + Minus = GLFW_KEY_MINUS, + Period = GLFW_KEY_PERIOD, + Slash = GLFW_KEY_SLASH, + Num0 = GLFW_KEY_0, + Num1 = GLFW_KEY_1, + Num2 = GLFW_KEY_2, + Num3 = GLFW_KEY_3, + Num4 = GLFW_KEY_4, + Num5 = GLFW_KEY_5, + Num6 = GLFW_KEY_6, + Num7 = GLFW_KEY_7, + Num8 = GLFW_KEY_8, + Num9 = GLFW_KEY_9, + Semicolon = GLFW_KEY_SEMICOLON, + Equals = GLFW_KEY_EQUAL, + A = GLFW_KEY_A, + B = GLFW_KEY_B, + C = GLFW_KEY_C, + D = GLFW_KEY_D, + E = GLFW_KEY_E, + F = GLFW_KEY_F, + G = GLFW_KEY_G, + H = GLFW_KEY_H, + I = GLFW_KEY_I, + J = GLFW_KEY_J, + K = GLFW_KEY_K, + L = GLFW_KEY_L, + M = GLFW_KEY_M, + N = GLFW_KEY_N, + O = GLFW_KEY_O, + P = GLFW_KEY_P, + Q = GLFW_KEY_Q, + R = GLFW_KEY_R, + S = GLFW_KEY_S, + T = GLFW_KEY_T, + U = GLFW_KEY_U, + V = GLFW_KEY_V, + W = GLFW_KEY_W, + X = GLFW_KEY_X, + Y = GLFW_KEY_Y, + Z = GLFW_KEY_Z, + LeftBracket = GLFW_KEY_LEFT_BRACKET, + Backslash = GLFW_KEY_BACKSLASH, + RightBracket = GLFW_KEY_RIGHT_BRACKET, + GraveAccent = GLFW_KEY_GRAVE_ACCENT, + World1 = GLFW_KEY_WORLD_1, + World2 = GLFW_KEY_WORLD_2, + Escape = GLFW_KEY_ESCAPE, + Enter = GLFW_KEY_ENTER, + Tab = GLFW_KEY_TAB, + Backspace = GLFW_KEY_BACKSPACE, + Insert = GLFW_KEY_INSERT, + Delete = GLFW_KEY_DELETE, + Right = GLFW_KEY_RIGHT, + Left = GLFW_KEY_LEFT, + Down = GLFW_KEY_DOWN, + Up = GLFW_KEY_UP, + PageUp = GLFW_KEY_PAGE_UP, + PageDown = GLFW_KEY_PAGE_DOWN, + Home = GLFW_KEY_HOME, + End = GLFW_KEY_END, + CapsLock = GLFW_KEY_CAPS_LOCK, + ScrollLock = GLFW_KEY_SCROLL_LOCK, + NumLock = GLFW_KEY_NUM_LOCK, + PrintScreen = GLFW_KEY_PRINT_SCREEN, + Pause = GLFW_KEY_PAUSE, + F1 = GLFW_KEY_F1, + F2 = GLFW_KEY_F2, + F3 = GLFW_KEY_F3, + F4 = GLFW_KEY_F4, + F5 = GLFW_KEY_F5, + F6 = GLFW_KEY_F6, + F7 = GLFW_KEY_F7, + F8 = GLFW_KEY_F8, + F9 = GLFW_KEY_F9, + F10 = GLFW_KEY_F10, + F11 = GLFW_KEY_F11, + F12 = GLFW_KEY_F12, + F13 = GLFW_KEY_F13, + F14 = GLFW_KEY_F14, + F15 = GLFW_KEY_F15, + F16 = GLFW_KEY_F16, + F17 = GLFW_KEY_F17, + F18 = GLFW_KEY_F18, + F19 = GLFW_KEY_F19, + F20 = GLFW_KEY_F20, + F21 = GLFW_KEY_F21, + F22 = GLFW_KEY_F22, + F23 = GLFW_KEY_F23, + F24 = GLFW_KEY_F24, + F25 = GLFW_KEY_F25, + KeyPad0 = GLFW_KEY_KP_0, + KeyPad1 = GLFW_KEY_KP_1, + KeyPad2 = GLFW_KEY_KP_2, + KeyPad3 = GLFW_KEY_KP_3, + KeyPad4 = GLFW_KEY_KP_4, + KeyPad5 = GLFW_KEY_KP_5, + KeyPad6 = GLFW_KEY_KP_6, + KeyPad7 = GLFW_KEY_KP_7, + KeyPad8 = GLFW_KEY_KP_8, + KeyPad9 = GLFW_KEY_KP_9, + KeyPadDecimal = GLFW_KEY_KP_DECIMAL, + KeyPadDivide = GLFW_KEY_KP_DIVIDE, + KeyPadMultiply = GLFW_KEY_KP_MULTIPLY, + KeyPadSubtract = GLFW_KEY_KP_SUBTRACT, + KeyPadAdd = GLFW_KEY_KP_ADD, + KeyPadEnter = GLFW_KEY_KP_ENTER, + KeyPadEqual = GLFW_KEY_KP_EQUAL, + Menu = GLFW_KEY_MENU, + }; + + + class Key { + public: + constexpr Key(Keys key) :m_key(static_cast(key)) { } + + auto operator<=>(const Key&) const = default; + + private: + u32 m_key; + }; + + class Shortcut { + public: + + Shortcut operator+(const Key &other) const { + Shortcut result = *this; + result.m_keys.insert(other); + + return result; + } + + Shortcut& operator+=(const Key &other) { + this->m_keys.insert(other); + + return *this; + } + + auto operator<=>(const Shortcut&) const = default; + private: + friend Shortcut operator+(const Key &lhs, const Key &rhs); + + std::set m_keys; + }; + + inline Shortcut operator+(const Key &lhs, const Key &rhs) { + Shortcut result; + result.m_keys = { lhs, rhs }; + + return result; + } + + static constexpr auto CTRL = Key(static_cast(0x1000'0000)); + static constexpr auto ALT = Key(static_cast(0x2000'0000)); + static constexpr auto SHIFT = Key(static_cast(0x3000'0000)); + static constexpr auto SUPER = Key(static_cast(0x4000'0000)); + + class ShortcutManager { + public: + static void addGlobalShortcut(const Shortcut &shortcut, const std::function &callback); + static void addShortcut(View *view, const Shortcut &shortcut, const std::function &callback); + static void process(View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode); + }; + +} \ No newline at end of file diff --git a/plugins/libimhex/include/hex/helpers/shared_data.hpp b/plugins/libimhex/include/hex/helpers/shared_data.hpp index 686169723..60664f616 100644 --- a/plugins/libimhex/include/hex/helpers/shared_data.hpp +++ b/plugins/libimhex/include/hex/helpers/shared_data.hpp @@ -79,6 +79,8 @@ namespace hex { static std::vector footerItems; static std::vector toolbarItems; + static std::map> globalShortcuts; + static std::mutex tasksMutex; static std::list runningTasks; diff --git a/plugins/libimhex/include/hex/views/view.hpp b/plugins/libimhex/include/hex/views/view.hpp index d3abf368f..2c9a52e4d 100644 --- a/plugins/libimhex/include/hex/views/view.hpp +++ b/plugins/libimhex/include/hex/views/view.hpp @@ -33,7 +33,6 @@ namespace hex { virtual void drawContent() = 0; virtual void drawAlwaysVisible() { } virtual void drawMenu(); - virtual bool handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt); virtual bool isAvailable(); virtual bool shouldProcess() { return this->isAvailable() && this->getWindowOpenState(); } @@ -64,6 +63,9 @@ namespace hex { private: std::string m_unlocalizedViewName; bool m_windowOpen = false; + std::map> m_shortcuts; + + friend class ShortcutManager; }; } \ No newline at end of file diff --git a/plugins/libimhex/source/api/keybinding.cpp b/plugins/libimhex/source/api/keybinding.cpp new file mode 100644 index 000000000..149923358 --- /dev/null +++ b/plugins/libimhex/source/api/keybinding.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + +#include + +namespace hex { + + void ShortcutManager::addGlobalShortcut(const Shortcut &shortcut, const std::function &callback) { + SharedData::globalShortcuts.insert({ shortcut, callback }); + } + + void ShortcutManager::addShortcut(View *view, const Shortcut &shortcut, const std::function &callback) { + view->m_shortcuts.insert({ shortcut, callback }); + } + + void ShortcutManager::process(View *currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) { + Shortcut pressedShortcut; + + if (ctrl) + pressedShortcut += CTRL; + if (alt) + pressedShortcut += ALT; + if (shift) + pressedShortcut += SHIFT; + if (super) + pressedShortcut += SUPER; + + pressedShortcut += static_cast(keyCode); + + if (focused && currentView->m_shortcuts.contains(pressedShortcut)) + currentView->m_shortcuts[pressedShortcut](); + else if (SharedData::globalShortcuts.contains(pressedShortcut)) + SharedData::globalShortcuts[pressedShortcut](); + } + +} \ No newline at end of file diff --git a/plugins/libimhex/source/helpers/shared_data.cpp b/plugins/libimhex/source/helpers/shared_data.cpp index e20d90544..143277f0d 100644 --- a/plugins/libimhex/source/helpers/shared_data.cpp +++ b/plugins/libimhex/source/helpers/shared_data.cpp @@ -29,6 +29,8 @@ namespace hex { std::vector SharedData::footerItems; std::vector SharedData::toolbarItems; + std::map> SharedData::globalShortcuts; + std::mutex SharedData::tasksMutex; std::list SharedData::runningTasks; diff --git a/plugins/libimhex/source/views/view.cpp b/plugins/libimhex/source/views/view.cpp index bf43731b8..3d4edda42 100644 --- a/plugins/libimhex/source/views/view.cpp +++ b/plugins/libimhex/source/views/view.cpp @@ -13,7 +13,6 @@ namespace hex { View::View(std::string unlocalizedName) : m_unlocalizedViewName(unlocalizedName) { } void View::drawMenu() { } - bool View::handleShortcut(bool keys[512], bool ctrl, bool shift, bool alt) { return false; } bool View::isAvailable() { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isAvailable(); diff --git a/source/window/window.cpp b/source/window/window.cpp index 75c5f4f62..031591840 100644 --- a/source/window/window.cpp +++ b/source/window/window.cpp @@ -493,12 +493,6 @@ namespace hex { } void Window::frame() { - bool pressedKeys[512] = { false }; - - for (u16 i = 0; i < 512; i++) - pressedKeys[i] = ImGui::GetIO().KeysDown[i] && !this->m_prevKeysDown[i]; - std::copy_n(ImGui::GetIO().KeysDown, 512, this->m_prevKeysDown); - for (const auto &call : View::getDeferedCalls()) call(); View::getDeferedCalls().clear(); @@ -522,10 +516,25 @@ namespace hex { view->drawContent(); } - view->handleShortcut(pressedKeys, ImGui::GetIO().KeyCtrl, ImGui::GetIO().KeyShift, ImGui::GetIO().KeyAlt); - } + { + bool hasWindow = ImGui::FindWindowByName(View::toWindowName(view->getUnlocalizedName()).c_str()) != nullptr; + bool focused = false; - #ifdef DEBUG + if (hasWindow) { + ImGui::Begin(View::toWindowName(view->getUnlocalizedName()).c_str()); + focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows); + ImGui::End(); + } + + auto &io = ImGui::GetIO(); + for (const auto &key : this->m_pressedKeys) { + ShortcutManager::process(view, io.KeyCtrl, io.KeyAlt, io.KeyShift, io.KeySuper, focused, key); + } + } + } + this->m_pressedKeys.clear(); + +#ifdef DEBUG if (this->m_demoWindowOpen) { ImGui::ShowDemoWindow(&this->m_demoWindowOpen); ImPlot::ShowDemoWindow(&this->m_demoWindowOpen); @@ -820,8 +829,12 @@ namespace hex { if (keyName != nullptr) key = std::toupper(keyName[0]); + auto win = static_cast(glfwGetWindowUserPointer(window)); + if (action == GLFW_PRESS) { auto &io = ImGui::GetIO(); + + win->m_pressedKeys.push_back(key); io.KeysDown[key] = true; io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0; io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0;