diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6ef1354e..d3614a655 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,7 +56,11 @@ configurePackageCreation()
add_executable(imhex ${application_type}
source/main.cpp
- source/window.cpp
+
+ source/window/window.cpp
+ source/window/win_window.cpp
+ source/window/macos_window.cpp
+ source/window/linux_window.cpp
source/init/splash_window.cpp
source/init/tasks.cpp
@@ -94,7 +98,7 @@ set_target_properties(imhex PROPERTIES CXX_VISIBILITY_PRESET hidden)
target_link_directories(imhex PRIVATE ${CAPSTONE_LIBRARY_DIRS} ${MAGIC_LIBRARY_DIRS})
if (WIN32)
- target_link_libraries(imhex magic ${CMAKE_DL_LIBS} capstone LLVMDemangle libimhex ${Python_LIBRARIES} wsock32 ws2_32 libyara)
+ target_link_libraries(imhex magic ${CMAKE_DL_LIBS} capstone LLVMDemangle libimhex ${Python_LIBRARIES} wsock32 ws2_32 libyara Dwmapi.lib)
else ()
target_link_libraries(imhex magic ${CMAKE_DL_LIBS} capstone LLVMDemangle libimhex ${Python_LIBRARIES} dl pthread libyara)
endif ()
diff --git a/README.md b/README.md
index 6a40b1fda..24ac395ac 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
:mag: ImHex
-A Hex Editor for Reverse Engineers, Programmers and people that value their eye sight when working at 3 AM.
+A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.
diff --git a/external/ImGui/include/imgui_imhex_extensions.h b/external/ImGui/include/imgui_imhex_extensions.h
index 61443d1d2..d03f24eeb 100644
--- a/external/ImGui/include/imgui_imhex_extensions.h
+++ b/external/ImGui/include/imgui_imhex_extensions.h
@@ -6,6 +6,26 @@
namespace ImGui {
+ struct Texture {
+ ImTextureID textureId;
+ int width, height;
+
+ [[nodiscard]]
+ constexpr bool valid() const noexcept {
+ return this->textureId != nullptr;
+ }
+
+ [[nodiscard]]
+ constexpr operator ImTextureID() {
+ return this->textureId;
+ }
+
+ [[nodiscard]]
+ auto size() const noexcept {
+ return ImVec2(this->width, this->height);
+ }
+ };
+
bool IconHyperlink(const char *icon, const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool Hyperlink(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
bool BulletHyperlink(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
@@ -22,9 +42,9 @@ namespace ImGui {
return static_cast(ImGui::GetTime() * 100) % 100 <= static_cast(ImGui::GetIO().DeltaTime * 100);
}
- std::tuple LoadImageFromPath(const char *path);
- std::tuple LoadImageFromMemory(ImU8 *buffer, int size);
- void UnloadImage(ImTextureID texture);
+ Texture LoadImageFromPath(const char *path);
+ Texture LoadImageFromMemory(ImU8 *buffer, int size);
+ void UnloadImage(Texture &texture);
enum ImGuiCustomCol {
ImGuiCustomCol_DescButton,
diff --git a/external/ImGui/include/imgui_impl_glfw.h b/external/ImGui/include/imgui_impl_glfw.h
index 6abb40564..079255fcf 100644
--- a/external/ImGui/include/imgui_impl_glfw.h
+++ b/external/ImGui/include/imgui_impl_glfw.h
@@ -32,4 +32,4 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
-IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
+IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
\ No newline at end of file
diff --git a/external/ImGui/source/imgui_imhex_extensions.cpp b/external/ImGui/source/imgui_imhex_extensions.cpp
index 43c69a091..b260feadc 100644
--- a/external/ImGui/source/imgui_imhex_extensions.cpp
+++ b/external/ImGui/source/imgui_imhex_extensions.cpp
@@ -235,7 +235,7 @@ namespace ImGui {
colors[ImGuiCustomCol_DescButtonActive] = ImColor(80, 80, 120);
}
- std::tuple LoadImageFromPath(const char *path) {
+ Texture LoadImageFromPath(const char *path) {
int imageWidth = 0;
int imageHeight = 0;
@@ -261,7 +261,7 @@ namespace ImGui {
return { reinterpret_cast(static_cast(texture)), imageWidth, imageHeight };
}
- std::tuple LoadImageFromMemory(ImU8 *buffer, int size) {
+ Texture LoadImageFromMemory(ImU8 *buffer, int size) {
int imageWidth = 0;
int imageHeight = 0;
@@ -288,12 +288,14 @@ namespace ImGui {
return { reinterpret_cast(static_cast(texture)), imageWidth, imageHeight };
}
- void UnloadImage(ImTextureID texture) {
- if (texture == nullptr)
+ void UnloadImage(Texture &texture) {
+ if (texture.textureId == nullptr)
return;
- auto glTextureId = static_cast(reinterpret_cast(texture));
+ auto glTextureId = static_cast(reinterpret_cast(texture.textureId));
glDeleteTextures(1, &glTextureId);
+
+ texture = { nullptr, 0, 0 };
}
}
\ No newline at end of file
diff --git a/external/curl b/external/curl
index 31480dbd3..bfbde883a 160000
--- a/external/curl
+++ b/external/curl
@@ -1 +1 @@
-Subproject commit 31480dbd37fa7ea90bb9fa791b2716fc43ef6934
+Subproject commit bfbde883af33397943df68a3ae01847a634d33bf
diff --git a/include/window.hpp b/include/window.hpp
index 948735e48..ecb5f643e 100644
--- a/include/window.hpp
+++ b/include/window.hpp
@@ -8,9 +8,12 @@
#include
#include
+#include
+
struct GLFWwindow;
struct ImGuiSettingsHandler;
+
namespace hex {
class Window {
@@ -28,6 +31,10 @@ namespace hex {
bool setFont(const std::filesystem::path &font_path);
private:
+ void setupNativeWindow();
+ void updateNativeWindow();
+ void drawTitleBar();
+
void frameBegin();
void frame();
void frameEnd();
@@ -47,14 +54,18 @@ namespace hex {
bool m_demoWindowOpen = false;
bool m_layoutConfigured = false;
+ std::string m_windowTitle;
+
double m_lastFrameTime;
bool m_prevKeysDown[512];
std::string m_availableUpdate;
- u32 m_bannerWidth = 0, m_bannerHeight = 0;
- void *m_bannerTexture = nullptr;
+ ImGui::Texture m_bannerTexture;
+ ImGui::Texture m_logoTexture;
+
+
std::filesystem::path m_safetyBackupPath;
};
diff --git a/plugins/libimhex/include/hex/resources.hpp b/plugins/libimhex/include/hex/resources.hpp
index 0d556caeb..bccb657cd 100644
--- a/plugins/libimhex/include/hex/resources.hpp
+++ b/plugins/libimhex/include/hex/resources.hpp
@@ -9,6 +9,8 @@
RESOURCE_EXPORT(splash);
RESOURCE_EXPORT(banner_light);
RESOURCE_EXPORT(banner_dark);
+RESOURCE_EXPORT(imhex_logo);
+
RESOURCE_EXPORT(cacert);
diff --git a/plugins/libimhex/source/resources.cpp b/plugins/libimhex/source/resources.cpp
index 1cf152223..d8dfe7ff6 100644
--- a/plugins/libimhex/source/resources.cpp
+++ b/plugins/libimhex/source/resources.cpp
@@ -46,5 +46,6 @@
RESOURCE(banner_light, "../../../res/resources/banner_light.png");
RESOURCE(banner_dark, "../../../res/resources/banner_dark.png");
RESOURCE(splash, "../../../res/resources/splash.png");
+RESOURCE(imhex_logo, "../../../res/resources/logo.png");
RESOURCE(cacert, "../../../res/resources/cacert.pem");
\ No newline at end of file
diff --git a/res/resources/logo.png b/res/resources/logo.png
new file mode 100644
index 000000000..796d7cfa9
Binary files /dev/null and b/res/resources/logo.png differ
diff --git a/source/init/splash_window.cpp b/source/init/splash_window.cpp
index 8044a1fbe..a6ce1e492 100644
--- a/source/init/splash_window.cpp
+++ b/source/init/splash_window.cpp
@@ -67,10 +67,9 @@ namespace hex::init {
}
bool WindowSplash::loop() {
- ImTextureID splashTexture;
- u32 splashWidth, splashHeight;
+ ImGui::Texture splashTexture;
- std::tie(splashTexture, splashWidth, splashHeight) = ImGui::LoadImageFromMemory(splash, splash_size);
+ splashTexture = ImGui::LoadImageFromMemory(splash, splash_size);
if (splashTexture == nullptr) {
log::fatal("Could not load splash screen image!");
@@ -93,7 +92,7 @@ namespace hex::init {
auto drawList = ImGui::GetOverlayDrawList();
- drawList->AddImage(splashTexture, ImVec2(0, 0), ImVec2(splashWidth, splashHeight) * this->m_globalScale);
+ drawList->AddImage(splashTexture, ImVec2(0, 0), splashTexture.size() * this->m_globalScale);
drawList->AddText(ImVec2(15, 120) * this->m_globalScale, ImColor(0xFF, 0xFF, 0xFF, 0xFF), hex::format("WerWolv 2020 - {0}", &__DATE__[7]).c_str());
@@ -103,8 +102,8 @@ namespace hex::init {
drawList->AddText(ImVec2(15, 140) * this->m_globalScale, ImColor(0xFF, 0xFF, 0xFF, 0xFF), hex::format("{0}", IMHEX_VERSION).c_str());
#endif
- drawList->AddRectFilled(ImVec2(0, splashHeight - 5) * this->m_globalScale, ImVec2(splashWidth * this->m_progress, splashHeight) * this->m_globalScale, 0xFFFFFFFF);
- drawList->AddText(ImVec2(15, splashHeight - 25) * this->m_globalScale, ImColor(0xFF, 0xFF, 0xFF, 0xFF),
+ drawList->AddRectFilled(ImVec2(0, splashTexture.size().y - 5) * this->m_globalScale, ImVec2(splashTexture.size().x * this->m_progress, splashTexture.size().y) * this->m_globalScale, 0xFFFFFFFF);
+ drawList->AddText(ImVec2(15, splashTexture.size().y - 25) * this->m_globalScale, ImColor(0xFF, 0xFF, 0xFF, 0xFF),
hex::format("[{}] {}", "|/-\\"[ImU32(ImGui::GetTime() * 15) % 4], this->m_currTaskName).c_str());
}
diff --git a/source/window/linux_window.cpp b/source/window/linux_window.cpp
new file mode 100644
index 000000000..fc0acf5e5
--- /dev/null
+++ b/source/window/linux_window.cpp
@@ -0,0 +1,17 @@
+#include "window.hpp"
+
+#if defined(OS_LINUX)
+
+ namespace hex {
+
+ void Window::setupNativeWindow() {
+
+ }
+
+ void Window::updateNativeWindow() {
+
+ }
+
+ }
+
+#endif
\ No newline at end of file
diff --git a/source/window/macos_window.cpp b/source/window/macos_window.cpp
new file mode 100644
index 000000000..8ff09a68d
--- /dev/null
+++ b/source/window/macos_window.cpp
@@ -0,0 +1,17 @@
+#include "window.hpp"
+
+#if defined(OS_MACOS)
+
+ namespace hex {
+
+ void Window::setupNativeWindow() {
+
+ }
+
+ void Window::updateNativeWindow() {
+
+ }
+
+ }
+
+#endif
\ No newline at end of file
diff --git a/source/window/win_window.cpp b/source/window/win_window.cpp
new file mode 100644
index 000000000..9a28c64ea
--- /dev/null
+++ b/source/window/win_window.cpp
@@ -0,0 +1,184 @@
+#include "window.hpp"
+
+#if defined(OS_WINDOWS)
+
+ #include
+
+ #include
+ #define GLFW_EXPOSE_NATIVE_WIN32
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include
+
+ namespace hex {
+ static LONG_PTR oldWndProc;
+ static float titleBarHeight;
+ static ImGuiMouseCursor mouseCursorIcon;
+
+ LRESULT wndProcImHex(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ switch (uMsg) {
+ case WM_NCCALCSIZE: {
+ auto& params = *reinterpret_cast(lParam);
+ RECT &rect = params.rgrc[0];
+
+ WINDOWPLACEMENT placement;
+ if (!::GetWindowPlacement(hwnd, &placement) || placement.showCmd != SW_MAXIMIZE)
+ return 0;
+
+ auto monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
+ if (monitor == nullptr) {
+ return 0;
+ }
+
+ MONITORINFO monitor_info{};
+ monitor_info.cbSize = sizeof(monitor_info);
+ if (!::GetMonitorInfoW(monitor, &monitor_info))
+ return 0;
+
+ rect = monitor_info.rcWork;
+
+ return 0;
+ }
+ case WM_SETCURSOR: {
+ auto cursorPos = LOWORD(lParam);
+
+ switch (cursorPos) {
+ case HTRIGHT:
+ case HTLEFT:
+ mouseCursorIcon = ImGuiMouseCursor_ResizeEW;
+ return TRUE;
+ case HTTOP:
+ case HTBOTTOM:
+ mouseCursorIcon = ImGuiMouseCursor_ResizeNS;
+ return TRUE;
+ case HTTOPLEFT:
+ case HTBOTTOMRIGHT:
+ mouseCursorIcon = ImGuiMouseCursor_ResizeNWSE;
+ return TRUE;
+ case HTTOPRIGHT:
+ case HTBOTTOMLEFT:
+ mouseCursorIcon = ImGuiMouseCursor_ResizeNESW;
+ return TRUE;
+ default:
+ mouseCursorIcon = ImGuiMouseCursor_None;
+ return TRUE;
+ }
+ }
+ case WM_NCHITTEST: {
+ POINT cursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+
+ const POINT border{
+ ::GetSystemMetrics(SM_CXFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER),
+ ::GetSystemMetrics(SM_CYFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)
+ };
+ RECT window;
+ if (!::GetWindowRect(hwnd, &window)) {
+ return HTNOWHERE;
+ }
+
+ constexpr auto RegionClient = 0b0000;
+ constexpr auto RegionLeft = 0b0001;
+ constexpr auto RegionRight = 0b0010;
+ constexpr auto RegionTop = 0b0100;
+ constexpr auto RegionBottom = 0b1000;
+
+ const auto result =
+ RegionLeft * (cursor.x < (window.left + border.x)) |
+ RegionRight * (cursor.x >= (window.right - border.x)) |
+ RegionTop * (cursor.y < (window.top + border.y)) |
+ RegionBottom * (cursor.y >= (window.bottom - border.y));
+
+ switch (result) {
+ case RegionLeft:
+ return HTLEFT;
+ case RegionRight:
+ return HTRIGHT;
+ case RegionTop:
+ return HTTOP;
+ case RegionBottom:
+ return HTBOTTOM;
+ case RegionTop | RegionLeft:
+ return HTTOPLEFT;
+ case RegionTop | RegionRight:
+ return HTTOPRIGHT;
+ case RegionBottom | RegionLeft:
+ return HTBOTTOMLEFT;
+ case RegionBottom | RegionRight:
+ return HTBOTTOMRIGHT;
+ case RegionClient:
+ if ((cursor.y < (window.top + titleBarHeight)) && !ImGui::IsAnyItemHovered())
+ return HTCAPTION;
+ else break;
+ }
+ }
+ }
+
+ return CallWindowProc((WNDPROC)oldWndProc, hwnd, uMsg, wParam, lParam);
+ }
+
+ void Window::setupNativeWindow() {
+ auto hwnd = glfwGetWin32Window(this->m_window);
+ oldWndProc = SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wndProcImHex);
+ MARGINS borderless = {1,1,1,1};
+ DwmExtendFrameIntoClientArea(hwnd, &borderless);
+ SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE);
+ SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_POPUP | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU);
+ }
+
+ void Window::updateNativeWindow() {
+ titleBarHeight = ImGui::GetCurrentWindow()->MenuBarHeight();
+
+ if (mouseCursorIcon != ImGuiMouseCursor_None)
+ ImGui::SetMouseCursor(mouseCursorIcon);
+ }
+
+ void Window::drawTitleBar() {
+ auto buttonSize = ImVec2(titleBarHeight * 1.5F, titleBarHeight);
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_MenuBarBg));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered));
+
+ ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 6);
+ #if defined(DEBUG)
+ if (ImGui::Button(ICON_VS_DEBUG, buttonSize))
+ hex::openWebpage("https://imhex.werwolv.net/debug");
+ #endif
+ if (ImGui::Button(ICON_VS_SMILEY, buttonSize))
+ hex::openWebpage("mailto://hey@werwolv.net");
+
+ ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 3);
+ if (ImGui::Button(ICON_VS_CHROME_MINIMIZE, buttonSize))
+ glfwIconifyWindow(this->m_window);
+ if (glfwGetWindowAttrib(this->m_window, GLFW_MAXIMIZED)) {
+ if (ImGui::Button(ICON_VS_CHROME_RESTORE, buttonSize))
+ glfwRestoreWindow(this->m_window);
+ } else {
+ if (ImGui::Button(ICON_VS_CHROME_MAXIMIZE, buttonSize))
+ glfwMaximizeWindow(this->m_window);
+ }
+
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, 0xFF7A70F1);
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, 0xFF2311E8);
+
+
+ if (ImGui::Button(ICON_VS_CHROME_CLOSE, buttonSize)) {
+ EventManager::post();
+ EventManager::post(this->m_window);
+ }
+
+ ImGui::PopStyleColor(5);
+ ImGui::PopStyleVar();
+
+ ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize(this->m_windowTitle.c_str()).x) / 2);
+ ImGui::TextUnformatted(this->m_windowTitle.c_str());
+ }
+
+ }
+
+#endif
\ No newline at end of file
diff --git a/source/window.cpp b/source/window/window.cpp
similarity index 89%
rename from source/window.cpp
rename to source/window/window.cpp
index 58a14a6ad..3748d657f 100644
--- a/source/window.cpp
+++ b/source/window/window.cpp
@@ -80,33 +80,35 @@ namespace hex {
{
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
- if (this->m_bannerTexture != nullptr)
+ if (this->m_bannerTexture.valid())
ImGui::UnloadImage(this->m_bannerTexture);
if (theme.is_number()) {
switch (static_cast(theme)) {
default:
- case 0: /* Dark theme */
- ImGui::StyleColorsDark();
- ImGui::StyleCustomColorsDark();
- ImPlot::StyleColorsDark();
- std::tie(this->m_bannerTexture, this->m_bannerWidth, this->m_bannerHeight) = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
- break;
- case 1: /* Light theme */
- ImGui::StyleColorsLight();
- ImGui::StyleCustomColorsLight();
- ImPlot::StyleColorsLight();
- std::tie(this->m_bannerTexture, this->m_bannerWidth, this->m_bannerHeight) = ImGui::LoadImageFromMemory(banner_light, banner_light_size); break;
- case 2: /* Classic theme */
- ImGui::StyleColorsClassic();
- ImGui::StyleCustomColorsClassic();
- ImPlot::StyleColorsClassic();
- std::tie(this->m_bannerTexture, this->m_bannerWidth, this->m_bannerHeight) = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size); break;
+ case 0: /* Dark theme */
+ ImGui::StyleColorsDark();
+ ImGui::StyleCustomColorsDark();
+ ImPlot::StyleColorsDark();
+ this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
+ break;
+ case 1: /* Light theme */
+ ImGui::StyleColorsLight();
+ ImGui::StyleCustomColorsLight();
+ ImPlot::StyleColorsLight();
+ this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_light, banner_light_size);
+ break;
+ case 2: /* Classic theme */
+ ImGui::StyleColorsClassic();
+ ImGui::StyleCustomColorsClassic();
+ ImPlot::StyleColorsClassic();
+ this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
+ break;
}
ImGui::GetStyle().Colors[ImGuiCol_DockingEmptyBg] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
- if (this->m_bannerTexture == nullptr) {
+ if (!this->m_bannerTexture.valid()) {
log::fatal("Failed to load banner texture!");
exit(EXIT_FAILURE);
}
@@ -181,6 +183,7 @@ namespace hex {
if (ProjectFile::hasUnsavedChanges())
title += " (*)";
+ this->m_windowTitle = title;
glfwSetWindowTitle(this->m_window, title.c_str());
});
@@ -217,6 +220,8 @@ namespace hex {
std::signal(SIGILL, signalHandler);
std::signal(SIGABRT, signalHandler);
std::signal(SIGFPE, signalHandler);
+
+ this->m_logoTexture = ImGui::LoadImageFromMemory(imhex_logo, imhex_logo_size);
}
Window::~Window() {
@@ -229,6 +234,7 @@ namespace hex {
EventManager::unsubscribe(this);
ImGui::UnloadImage(this->m_bannerTexture);
+ ImGui::UnloadImage(this->m_logoTexture);
}
void Window::loop() {
@@ -320,10 +326,10 @@ namespace hex {
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking
- | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse
- | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize
- | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoBringToFrontOnFocus
- | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
+ | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse
+ | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize
+ | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoBringToFrontOnFocus
+ | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
@@ -348,40 +354,40 @@ namespace hex {
if (ImGui::BeginMenuBar()) {
+ auto menuBarHeight = ImGui::GetCurrentWindow()->MenuBarHeight();
+ ImGui::SetCursorPosX(5);
+ ImGui::Image(this->m_logoTexture, ImVec2(menuBarHeight, menuBarHeight));
+
for (const auto& menu : { "hex.menu.file"_lang, "hex.menu.edit"_lang, "hex.menu.view"_lang, "hex.menu.help"_lang })
if (ImGui::BeginMenu(menu)) ImGui::EndMenu();
- if (ImGui::BeginMenu("hex.menu.view"_lang)) {
- for (auto &view : ContentRegistry::Views::getEntries()) {
- if (view->hasViewMenuItemEntry())
- ImGui::MenuItem((LangEntry(view->getUnlocalizedName()) + " " + "hex.menu.view"_lang).c_str(), "", &view->getWindowOpenState());
+ if (ImGui::BeginMenu("hex.menu.view"_lang)) {
+ for (auto &view : ContentRegistry::Views::getEntries()) {
+ if (view->hasViewMenuItemEntry())
+ ImGui::MenuItem((LangEntry(view->getUnlocalizedName()) + " " + "hex.menu.view"_lang).c_str(), "", &view->getWindowOpenState());
+ }
+ ImGui::EndMenu();
}
- ImGui::EndMenu();
- }
- for (auto &view : ContentRegistry::Views::getEntries()) {
- view->drawMenu();
- }
+ for (auto &view : ContentRegistry::Views::getEntries()) {
+ view->drawMenu();
+ }
- if (ImGui::BeginMenu("hex.menu.view"_lang)) {
+ if (ImGui::BeginMenu("hex.menu.view"_lang)) {
#if defined(DEBUG)
ImGui::Separator();
ImGui::MenuItem("hex.menu.view.demo"_lang, "", &this->m_demoWindowOpen);
#endif
- ImGui::EndMenu();
- }
+ ImGui::EndMenu();
+ }
- #if defined(DEBUG)
- ImGui::SameLine();
- ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 2 * ImGui::GetFontSize());
- ImGui::TextUnformatted(ICON_FA_BUG);
- #endif
+ this->drawTitleBar();
- ImGui::EndMenuBar();
+ ImGui::EndMenuBar();
}
if (SharedData::currentProvider == nullptr) {
- char title[256];
+ static char title[256];
ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", ImGui::GetCurrentWindow()->Name, ImGui::GetID("MainDock"));
if (ImGui::Begin(title)) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10 * this->m_globalScale, 10 * this->m_globalScale));
@@ -397,9 +403,12 @@ namespace hex {
this->resetLayout();
}
+ this->updateNativeWindow();
+
}
ImGui::End();
+
// Popup for when no plugins were loaded. Intentionally left untranslated because localization isn't available
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (ImGui::BeginPopupModal("No Plugins", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
@@ -467,12 +476,12 @@ namespace hex {
View::drawCommonInterfaces();
-#ifdef DEBUG
+ #ifdef DEBUG
if (this->m_demoWindowOpen) {
ImGui::ShowDemoWindow(&this->m_demoWindowOpen);
ImPlot::ShowDemoWindow(&this->m_demoWindowOpen);
}
-#endif
+ #endif
}
void Window::frameEnd() {
@@ -499,7 +508,7 @@ namespace hex {
void Window::drawWelcomeScreen() {
const auto availableSpace = ImGui::GetContentRegionAvail();
- ImGui::Image(this->m_bannerTexture, ImVec2(this->m_bannerWidth / (2 * (1.0F / this->m_globalScale)), this->m_bannerHeight / (2 * (1.0F / this->m_globalScale))));
+ ImGui::Image(this->m_bannerTexture, this->m_bannerTexture.size() / (2 * (1.0F / this->m_globalScale)));
ImGui::Indent();
if (ImGui::BeginTable("Welcome Left", 1, ImGuiTableFlags_NoBordersInBody, ImVec2(availableSpace.x / 2, 0))) {
@@ -507,7 +516,7 @@ namespace hex {
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 3);
ImGui::TableNextColumn();
- ImGui::TextWrapped("A Hex Editor for Reverse Engineers, Programmers and people that value their eye sight when working at 3 AM.");
+ ImGui::TextWrapped("A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.");
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 5);
ImGui::TableNextColumn();
@@ -663,7 +672,7 @@ namespace hex {
throw std::runtime_error("Failed to initialize GLFW!");
#ifdef __APPLE__
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
if (auto *monitor = glfwGetPrimaryMonitor(); monitor) {
@@ -679,7 +688,10 @@ namespace hex {
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- this->m_window = glfwCreateWindow(1280 * this->m_globalScale, 720 * this->m_globalScale, "ImHex", nullptr, nullptr);
+ this->m_windowTitle = "ImHex";
+ this->m_window = glfwCreateWindow(1280 * this->m_globalScale, 720 * this->m_globalScale, this->m_windowTitle.c_str(), nullptr, nullptr);
+
+ this->setupNativeWindow();
glfwSetWindowUserPointer(this->m_window, this);
@@ -689,30 +701,35 @@ namespace hex {
glfwMakeContextCurrent(this->m_window);
glfwSwapInterval(1);
- {
- int x = 0, y = 0;
- glfwGetWindowPos(this->m_window, &x, &y);
- SharedData::windowPos = ImVec2(x, y);
- }
+ {
+ int x = 0, y = 0;
+ glfwGetWindowPos(this->m_window, &x, &y);
+ SharedData::windowPos = ImVec2(x, y);
+ }
- {
- int width = 0, height = 0;
- glfwGetWindowSize(this->m_window, &width, &height);
- SharedData::windowSize = ImVec2(width, height);
- }
+ {
+ int width = 0, height = 0;
+ glfwGetWindowSize(this->m_window, &width, &height);
+ glfwSetWindowSize(this->m_window, width, height);
+ SharedData::windowSize = ImVec2(width, height);
+ }
- glfwSetWindowPosCallback(this->m_window, [](GLFWwindow *window, int x, int y) {
- SharedData::windowPos = ImVec2(x, y);
+ glfwSetWindowPosCallback(this->m_window, [](GLFWwindow *window, int x, int y) {
+ SharedData::windowPos = ImVec2(x, y);
- auto win = static_cast(glfwGetWindowUserPointer(window));
- win->frameBegin();
- win->frame();
- win->frameEnd();
- });
+ if (ImGui::GetCurrentContext()->WithinFrameScope) return;
+
+ auto win = static_cast(glfwGetWindowUserPointer(window));
+ win->frameBegin();
+ win->frame();
+ win->frameEnd();
+ });
glfwSetWindowSizeCallback(this->m_window, [](GLFWwindow *window, int width, int height) {
SharedData::windowSize = ImVec2(width, height);
+ if (ImGui::GetCurrentContext()->WithinFrameScope) return;
+
auto win = static_cast(glfwGetWindowUserPointer(window));
win->frameBegin();
win->frame();
@@ -770,7 +787,7 @@ namespace hex {
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard;
#if !defined(OS_LINUX)
- io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
+ io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
#endif