From f4b1a60bb8cd64fb780ab26b651785c30a1d2748 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Sun, 14 Jul 2024 15:50:32 -0500 Subject: [PATCH] feat: Implement cross-platform DPI scaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This replaces the Windows-only code with code that should work on all the platforms. Tested on Linux/Wayland. The “Scaling” option is now just treated like a normal UI zoom control for users who want a larger UI. This means “Native” scaling option is removed now since that does not mean anything. --- lib/libimhex/CMakeLists.txt | 1 + lib/libimhex/include/hex/api/imhex_api.hpp | 19 +- .../include/hex/helpers/utils_macos.hpp | 1 - lib/libimhex/include/hex/ui/glfw_di.h | 35 +++ lib/libimhex/source/api/imhex_api.cpp | 22 +- lib/libimhex/source/helpers/utils_macos.m | 4 - lib/libimhex/source/ui/glfw_di.cpp | 223 ++++++++++++++++++ .../imgui/custom/source/imgui_impl_glfw.cpp | 25 +- main/gui/source/init/splash_window.cpp | 47 ++-- main/gui/source/window/linux_window.cpp | 11 +- main/gui/source/window/macos_window.cpp | 7 +- main/gui/source/window/web_window.cpp | 3 +- main/gui/source/window/win_window.cpp | 39 +-- main/gui/source/window/window.cpp | 106 +++++---- plugins/builtin/romfs/lang/de_DE.json | 1 - plugins/builtin/romfs/lang/en_US.json | 1 - plugins/builtin/romfs/lang/es_ES.json | 1 - plugins/builtin/romfs/lang/hu_HU.json | 1 - plugins/builtin/romfs/lang/it_IT.json | 1 - plugins/builtin/romfs/lang/ja_JP.json | 1 - plugins/builtin/romfs/lang/ko_KR.json | 1 - plugins/builtin/romfs/lang/pt_BR.json | 1 - plugins/builtin/romfs/lang/zh_CN.json | 1 - plugins/builtin/romfs/lang/zh_TW.json | 1 - plugins/builtin/source/content/events.cpp | 5 +- plugins/builtin/source/content/init_tasks.cpp | 26 +- .../source/content/main_menu_items.cpp | 12 +- .../source/content/settings_entries.cpp | 17 +- .../builtin/source/content/welcome_screen.cpp | 2 +- plugins/fonts/source/font_loader.cpp | 2 +- 30 files changed, 421 insertions(+), 196 deletions(-) create mode 100644 lib/libimhex/include/hex/ui/glfw_di.h create mode 100644 lib/libimhex/source/ui/glfw_di.cpp diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index abcd9677faa54..9752d1aab0ace 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -45,6 +45,7 @@ set(LIBIMHEX_SOURCES source/providers/memory_provider.cpp source/providers/undo/stack.cpp + source/ui/glfw_di.cpp source/ui/imgui_imhex_extensions.cpp source/ui/view.cpp source/ui/popup.cpp diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp index 2ecd25c1b0394..0fb901ad27060 100644 --- a/lib/libimhex/include/hex/api/imhex_api.hpp +++ b/lib/libimhex/include/hex/api/imhex_api.hpp @@ -426,8 +426,8 @@ namespace hex { void setMainDockSpaceId(ImGuiID id); void setMainWindowHandle(GLFWwindow *window); - void setGlobalScale(float scale); - void setNativeScale(float scale); + void setContentScale(float scale); + void setUserScale(float scale); void setBorderlessWindowMode(bool enabled); void setMultiWindowMode(bool enabled); @@ -481,17 +481,22 @@ namespace hex { /** - * @brief Gets the current global scale - * @return The current global scale + * @brief Gets the current UI content scale + * @return The current UI content scale */ float getGlobalScale(); /** - * @brief Gets the current native scale - * @return The current native scale + * @brief Gets the current window content scale + * @return The current window content scale */ - float getNativeScale(); + float getContentScale(); + /** + * @brief Gets the current user scale + * @return The current user scale + */ + float getUserScale(); /** * @brief Gets the current main window position diff --git a/lib/libimhex/include/hex/helpers/utils_macos.hpp b/lib/libimhex/include/hex/helpers/utils_macos.hpp index 5c025356e99af..533a8a1cf8fa5 100644 --- a/lib/libimhex/include/hex/helpers/utils_macos.hpp +++ b/lib/libimhex/include/hex/helpers/utils_macos.hpp @@ -10,7 +10,6 @@ void openWebpageMacos(const char *url); bool isMacosSystemDarkModeEnabled(); bool isMacosFullScreenModeEnabled(GLFWwindow *window); - float getBackingScaleFactor(); void setupMacosWindowStyle(GLFWwindow *window, bool borderlessWindowMode); diff --git a/lib/libimhex/include/hex/ui/glfw_di.h b/lib/libimhex/include/hex/ui/glfw_di.h new file mode 100644 index 0000000000000..5289787c271a5 --- /dev/null +++ b/lib/libimhex/include/hex/ui/glfw_di.h @@ -0,0 +1,35 @@ +#pragma once + +struct GLFWwindow; +struct GLFWmonitor; +typedef void (* GLFWcursorposfun)(GLFWwindow* window, double diX, double diY); +typedef void (* GLFWframebuffersizefun)(GLFWwindow* window, int width, int height); +typedef void (* GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, float yscale); +typedef void (* GLFWwindowposfun)(GLFWwindow* window, int diX, int diY); +typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int diWidth, int diHeight); + +namespace hex { + /** + * Wrapper GLFW functions that use a device-independent coordinate system + * where the reference pixel is always 1/96in. + */ + namespace glfw { + GLFWwindow *CreateWindow(int diWidth, int diHeight, const char* title, GLFWmonitor* monitor, GLFWwindow* share); + void DestroyWindow(GLFWwindow *window); + void *GetWindowUserPointer(GLFWwindow *window); + void *SetWindowUserPointer(GLFWwindow *window, void *pointer); + void GetMonitorPos(GLFWmonitor *monitor, int *diX, int *diY); + bool GetMonitorSize(GLFWmonitor *monitor, int *diWidth, int *diHeight); + void SetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int diXpos, int diYpos, int diWidth, int diHeight, int refreshRate); + void GetWindowPos(GLFWwindow *window, int *diX, int *diY); + void SetWindowPos(GLFWwindow *window, int diX, int diY); + void GetWindowSize(GLFWwindow *window, int *diWidth, int *diHeight); + void SetWindowSize(GLFWwindow *window, int diWidth, int diHeight); + void SetWindowSizeLimits(GLFWwindow *window, int diMinWidth, int diMinHeight, int diMaxWidth, int diMaxHeight); + GLFWcursorposfun SetCursorPosCallback(GLFWwindow *window, GLFWcursorposfun callback); + GLFWwindowposfun SetFramebufferSizeCallback(GLFWwindow *window, GLFWframebuffersizefun callback); + GLFWwindowcontentscalefun SetWindowContentScaleCallback(GLFWwindow *window, GLFWwindowcontentscalefun callback); + GLFWwindowposfun SetWindowPosCallback(GLFWwindow *window, GLFWwindowposfun callback); + GLFWwindowsizefun SetWindowSizeCallback(GLFWwindow *window, GLFWwindowsizefun callback); + } +} diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index 4d48152c21a99..20ae7a97da83b 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -501,17 +501,16 @@ namespace hex { } - static float s_globalScale = 1.0; - void setGlobalScale(float scale) { - s_globalScale = scale; + static float s_contentScale = 1.0; + void setContentScale(float scale) { + s_contentScale = scale; } - static float s_nativeScale = 1.0; - void setNativeScale(float scale) { - s_nativeScale = scale; + static float s_userScale = 1.0; + void setUserScale(float scale) { + s_userScale = scale; } - static bool s_borderlessWindowMode; void setBorderlessWindowMode(bool enabled) { s_borderlessWindowMode = enabled; @@ -598,13 +597,16 @@ namespace hex { } float getGlobalScale() { - return impl::s_globalScale; + return getUserScale(); } - float getNativeScale() { - return impl::s_nativeScale; + float getContentScale() { + return impl::s_contentScale; } + float getUserScale() { + return impl::s_userScale; + } ImVec2 getMainWindowPosition() { if ((ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) != ImGuiConfigFlags_None) diff --git a/lib/libimhex/source/helpers/utils_macos.m b/lib/libimhex/source/helpers/utils_macos.m index 4436232b98e6a..6fe739cf8c9c6 100644 --- a/lib/libimhex/source/helpers/utils_macos.m +++ b/lib/libimhex/source/helpers/utils_macos.m @@ -42,10 +42,6 @@ bool isMacosSystemDarkModeEnabled(void) { } } - float getBackingScaleFactor(void) { - return [[NSScreen mainScreen] backingScaleFactor]; - } - void setupMacosWindowStyle(GLFWwindow *window, bool borderlessWindowMode) { NSWindow* cocoaWindow = glfwGetCocoaWindow(window); diff --git a/lib/libimhex/source/ui/glfw_di.cpp b/lib/libimhex/source/ui/glfw_di.cpp new file mode 100644 index 0000000000000..bf77330577115 --- /dev/null +++ b/lib/libimhex/source/ui/glfw_di.cpp @@ -0,0 +1,223 @@ +#include + +#include + +#include +#include + +namespace hex::glfw { + struct GlfwData { + void *userPointer = nullptr; + GLFWcursorposfun userCursorPosFn = nullptr; + GLFWframebuffersizefun userFramebufferSizeFn = nullptr; + GLFWwindowcontentscalefun userWindowContentScaleFn = nullptr; + GLFWwindowposfun userWindowPosFn = nullptr; + GLFWwindowsizefun userWindowSizeFn = nullptr; + float scaleX = 1.0F; + float scaleY = 1.0F; + }; + + static void RecalculateScale(GLFWwindow *window, GlfwData *data) { + int width, height, framebufferWidth, framebufferHeight; + float scaleX, scaleY; + glfwGetWindowSize(window, &width, &height); + glfwGetFramebufferSize(window, &framebufferWidth, &framebufferHeight); + glfwGetWindowContentScale(window, &scaleX, &scaleY); + data->scaleX = scaleX / (float(framebufferWidth) / width); + data->scaleY = scaleY / (float(framebufferHeight) / height); + } + + static GlfwData* GetWindowData(GLFWwindow *window) { + if (!window) + return nullptr; + + return static_cast(glfwGetWindowUserPointer(window)); + } + + template + void FromGLFW(GLFWwindow *window, T *x, T *y) { + auto data = GetWindowData(window); + if (!data) + throw std::runtime_error("Missing window data; did you use glfwCreateWindow directly instead of hex::glfw::CreateWindow?"); + if (x) + *x /= data->scaleX; + if (y) + *y /= data->scaleY; + } + + template + static void FromGLFW(GLFWmonitor *monitor, T *x, T *y) { + float xScale, yScale; + glfwGetMonitorContentScale(monitor, &xScale, &yScale); + if (x) + *x /= xScale; + if (y) + *y /= yScale; + } + + template + void ToGLFW(GLFWwindow *window, T *x, T *y) { + auto data = GetWindowData(window); + if (!data) + throw std::runtime_error("Missing window data; did you use glfwCreateWindow directly instead of hex::glfw::CreateWindow?"); + if (x) + *x *= data->scaleX; + if (y) + *y *= data->scaleY; + } + + template + static void ToGLFW(GLFWmonitor *monitor, T *x, T *y) { + float xScale, yScale; + glfwGetMonitorContentScale(monitor, &xScale, &yScale); + if (x) + *x *= xScale; + if (y) + *y *= yScale; + } + + GLFWwindow* CreateWindow(int diWidth, int diHeight, const char* title, GLFWmonitor* monitor, GLFWwindow* share) { + auto window = glfwCreateWindow(1, 1, title, monitor, share); + if (!window) + return nullptr; + + auto *data = new (std::nothrow) GlfwData; + if (!data) { + glfwDestroyWindow(window); + return nullptr; + } + + glfwSetWindowUserPointer(window, data); + RecalculateScale(window, data); + glfwSetWindowSize(window, diWidth * data->scaleX, diHeight * data->scaleY); + glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) { + auto data = GetWindowData(window); + RecalculateScale(window, data); + if (data->userFramebufferSizeFn) + (data->userFramebufferSizeFn)(window, width, height); + }); + glfwSetWindowContentScaleCallback(window, [](GLFWwindow *window, float scaleX, float scaleY) { + auto data = GetWindowData(window); + RecalculateScale(window, data); + if (data->userWindowContentScaleFn) + (data->userWindowContentScaleFn)(window, scaleX, scaleY); + }); + + return window; + } + + void DestroyWindow(GLFWwindow *window) { + if (!window) + return; + + delete GetWindowData(window); + glfwDestroyWindow(window); + } + + void *GetWindowUserPointer(GLFWwindow *window) { + if (!window) + return nullptr; + + return GetWindowData(window)->userPointer; + } + + void *SetWindowUserPointer(GLFWwindow *window, void *pointer) { + if (!window) + return nullptr; + + auto data = GetWindowData(window); + auto prev = data->userPointer; + data->userPointer = pointer; + return prev; + } + + bool GetMonitorSize(GLFWmonitor *monitor, int *diWidth, int *diHeight) { + auto mode = glfwGetVideoMode(monitor); + if (!mode) + return false; + + if (diWidth) + *diWidth = mode->width; + if (diHeight) + *diHeight = mode->height; + FromGLFW(monitor, diWidth, diHeight); + + return true; + } + + void GetMonitorPos(GLFWmonitor *monitor, int *diX, int *diY) { + glfwGetMonitorPos(monitor, diX, diY); + FromGLFW(monitor, diX, diY); + } + + void SetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int diXpos, int diYpos, int diWidth, int diHeight, int refreshRate) { + if (monitor) + ToGLFW(monitor, &diXpos, &diYpos); + else + ToGLFW(window, &diXpos, &diYpos); + + ToGLFW(window, &diWidth, &diHeight); + glfwSetWindowMonitor(window, monitor, diXpos, diYpos, diWidth, diHeight, refreshRate); + } + + void GetWindowPos(GLFWwindow *window, int *diX, int *diY) { + glfwGetWindowPos(window, diX, diY); + FromGLFW(window, diX, diY); + } + + void SetWindowPos(GLFWwindow *window, int diX, int diY) { + ToGLFW(window, &diX, &diY); + glfwSetWindowPos(window, diX, diY); + } + + void GetWindowSize(GLFWwindow *window, int *diWidth, int *diHeight) { + glfwGetWindowSize(window, diWidth, diHeight); + FromGLFW(window, diWidth, diHeight); + } + + void SetWindowSize(GLFWwindow *window, int diWidth, int diHeight) { + ToGLFW(window, &diWidth, &diHeight); + glfwSetWindowSize(window, diWidth, diHeight); + } + + void SetWindowSizeLimits(GLFWwindow *window, int diMinWidth, int diMinHeight, int diMaxWidth, int diMaxHeight) { + ToGLFW(window, + diMinWidth == GLFW_DONT_CARE ? nullptr : &diMinWidth, + diMinHeight == GLFW_DONT_CARE ? nullptr : &diMinHeight); + ToGLFW(window, + diMaxWidth == GLFW_DONT_CARE ? nullptr : &diMaxWidth, + diMaxHeight == GLFW_DONT_CARE ? nullptr : &diMaxHeight); + glfwSetWindowSizeLimits(window, diMinWidth, diMinHeight, diMaxWidth, diMaxHeight); + } + + #define IMHEX_WINDOW_CALLBACK_SCALE(fnName, cbType, paramType) \ + static void fnName##Wrapper(GLFWwindow *window, paramType x, paramType y) { \ + FromGLFW(window, &x, &y); \ + (GetWindowData(window)->user##fnName##Fn)(window, x, y); \ + } \ + \ + cbType Set##fnName##Callback(GLFWwindow *window, cbType callback) { \ + auto data = GetWindowData(window); \ + auto previous = data->user##fnName##Fn; \ + data->user##fnName##Fn = callback; \ + glfwSet##fnName##Callback(window, callback ? fnName##Wrapper : nullptr);\ + return previous; \ + } + + IMHEX_WINDOW_CALLBACK_SCALE(CursorPos, GLFWcursorposfun, double) + IMHEX_WINDOW_CALLBACK_SCALE(WindowPos, GLFWwindowposfun, int) + IMHEX_WINDOW_CALLBACK_SCALE(WindowSize, GLFWwindowsizefun, int) + #undef IMHEX_WINDOW_CALLBACK_SCALE + + #define IMHEX_WINDOW_CALLBACK_RECALC(fnName, cbType) \ + cbType Set##fnName##Callback(GLFWwindow *window, cbType callback) { \ + auto data = GetWindowData(window); \ + auto previous = data->user##fnName##Fn; \ + data->user##fnName##Fn = callback; \ + return previous; \ + } + + IMHEX_WINDOW_CALLBACK_RECALC(FramebufferSize, GLFWframebuffersizefun) + IMHEX_WINDOW_CALLBACK_RECALC(WindowContentScale, GLFWwindowcontentscalefun) + #undef IMHEX_WINDOW_CALLBACK_RECALC +} diff --git a/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp b/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp index b78f4429ef07d..a9aa77b9ee878 100644 --- a/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp +++ b/lib/third_party/imgui/custom/source/imgui_impl_glfw.cpp @@ -77,6 +77,7 @@ #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_glfw.h" +#include // Clang warnings with -Weverything #if defined(__clang__) @@ -164,6 +165,7 @@ struct ImGui_ImplGlfw_Data bool InstalledCallbacks; bool CallbacksChainForAllWindows; bool WantUpdateMonitors; + ImVec2 ScaleCoordinates; #ifdef __EMSCRIPTEN__ const char* CanvasSelector; #endif @@ -473,6 +475,8 @@ void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) x += window_x; y += window_y; } + x /= bd->ScaleCoordinates.x; + y /= bd->ScaleCoordinates.y; io.AddMousePosEvent((float)x, (float)y); bd->LastValidMousePos = ImVec2((float)x, (float)y); } @@ -611,6 +615,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->Window = window; bd->Time = 0.0; bd->WantUpdateMonitors = true; + bd->ScaleCoordinates = ImVec2(1.0F, 1.0F); // IMHEX PATCH BEGIN #ifdef __EMSCRIPTEN__ @@ -776,6 +781,8 @@ static void ImGui_ImplGlfw_UpdateMouseData() mouse_x += window_x; mouse_y += window_y; } + mouse_x /= bd->ScaleCoordinates.x; + mouse_y /= bd->ScaleCoordinates.y; bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y); io.AddMousePosEvent((float)mouse_x, (float)mouse_y); } @@ -929,7 +936,6 @@ static void ImGui_ImplGlfw_UpdateMonitors() // Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime. float x_scale, y_scale; glfwGetMonitorContentScale(glfw_monitors[n], &x_scale, &y_scale); - monitor.DpiScale = x_scale; // IMHEX PATCH BEGIN // REASON: Prevent occasional crash when a monitor connection status is changed @@ -951,11 +957,22 @@ void ImGui_ImplGlfw_NewFrame() // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h; + float scale_w, scale_h; glfwGetWindowSize(bd->Window, &w, &h); glfwGetFramebufferSize(bd->Window, &display_w, &display_h); + glfwGetWindowContentScale(bd->Window, &scale_w, &scale_h); io.DisplaySize = ImVec2((float)w, (float)h); if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h); + + bd->ScaleCoordinates = ImVec2(scale_w / io.DisplayFramebufferScale.x, scale_h / io.DisplayFramebufferScale.y); + if (std::abs(bd->ScaleCoordinates.x - 1.0F) < .001F && std::abs(bd->ScaleCoordinates.y - 1.0F) < .001F) { + bd->ScaleCoordinates = ImVec2(1.0F, 1.0F); + } else { + io.DisplaySize /= bd->ScaleCoordinates; + io.DisplayFramebufferScale = bd->ScaleCoordinates; + } + if (bd->WantUpdateMonitors) ImGui_ImplGlfw_UpdateMonitors(); @@ -1189,10 +1206,11 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport) static ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport) { + ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData; int x = 0, y = 0; glfwGetWindowPos(vd->Window, &x, &y); - return ImVec2((float)x, (float)y); + return ImVec2((float)x, (float)y) / bd->ScaleCoordinates; } static void ImGui_ImplGlfw_SetWindowPos(ImGuiViewport* viewport, ImVec2 pos) @@ -1207,7 +1225,7 @@ static ImVec2 ImGui_ImplGlfw_GetWindowSize(ImGuiViewport* viewport) ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData; int w = 0, h = 0; glfwGetWindowSize(vd->Window, &w, &h); - return ImVec2((float)w, (float)h); + return ImVec2((float)w, (float)h) / ImGui_ImplGlfw_GetBackendData()->ScaleCoordinates; } static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) @@ -1224,6 +1242,7 @@ static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) glfwSetWindowPos(vd->Window, x, y - height + size.y); #endif vd->IgnoreWindowSizeEventFrame = ImGui::GetFrameCount(); + size *= ImGui_ImplGlfw_GetBackendData()->ScaleCoordinates; glfwSetWindowSize(vd->Window, (int)size.x, (int)size.y); } diff --git a/main/gui/source/init/splash_window.cpp b/main/gui/source/init/splash_window.cpp index 5cb2d396030fc..3e9f6efef2125 100644 --- a/main/gui/source/init/splash_window.cpp +++ b/main/gui/source/init/splash_window.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -77,20 +78,20 @@ namespace hex::init { return; // Get information about the monitor - const GLFWvidmode *mode = glfwGetVideoMode(monitor); - if (!mode) + int monitorWidth, monitorHeight; + if (!hex::glfw::GetMonitorSize(monitor, &monitorWidth, &monitorHeight)) return; // Get the position of the monitor's viewport on the virtual screen int monitorX, monitorY; - glfwGetMonitorPos(monitor, &monitorX, &monitorY); + hex::glfw::GetMonitorPos(monitor, &monitorX, &monitorY); // Get the window size int windowWidth, windowHeight; - glfwGetWindowSize(window, &windowWidth, &windowHeight); + hex::glfw::GetWindowSize(window, &windowWidth, &windowHeight); // Center the splash screen on the monitor - glfwSetWindowPos(window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2); + hex::glfw::SetWindowPos(window, monitorX + (monitorWidth - windowWidth) / 2, monitorY + (monitorHeight - windowHeight) / 2); } static ImColor getHighlightColor(u32 index) { @@ -251,7 +252,7 @@ namespace hex::init { FrameResult WindowSplash::fullFrame() { - glfwSetWindowSize(m_window, 640, 400); + hex::glfw::SetWindowSize(m_window, 640, 400); centerWindow(m_window); glfwPollEvents(); @@ -426,7 +427,6 @@ namespace hex::init { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE); #else glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -445,8 +445,7 @@ namespace hex::init { glfwWindowHint(GLFW_FLOATING, GLFW_FALSE); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); - // Create the splash screen window - m_window = glfwCreateWindow(1, 1, "Starting ImHex...", nullptr, nullptr); + m_window = hex::glfw::CreateWindow(1, 1, "Starting ImHex...", nullptr, nullptr); if (m_window == nullptr) { hex::nativeErrorMessage(hex::format( "Failed to create GLFW window: [{}] {}.\n" @@ -460,26 +459,9 @@ namespace hex::init { // Force window to be fully opaque by default glfwSetWindowOpacity(m_window, 1.0F); - // Calculate native scale factor for hidpi displays - { - float xScale = 0, yScale = 0; - glfwGetWindowContentScale(m_window, &xScale, &yScale); - - auto meanScale = std::midpoint(xScale, yScale); - if (meanScale <= 0.0F) - meanScale = 1.0F; - - #if defined(OS_MACOS) - meanScale /= getBackingScaleFactor(); - #elif defined(OS_WEB) - meanScale = 1.0F; - #endif - - ImHexApi::System::impl::setGlobalScale(meanScale); - ImHexApi::System::impl::setNativeScale(meanScale); - - log::info("Native scaling set to: {:.1f}", meanScale); - } + float contentScale; + glfwGetWindowContentScale(m_window, &contentScale, nullptr); + ImHexApi::System::impl::setContentScale(contentScale); glfwMakeContextCurrent(m_window); glfwSwapInterval(1); @@ -503,8 +485,7 @@ namespace hex::init { #endif auto &io = ImGui::GetIO(); - - ImGui::GetStyle().ScaleAllSizes(ImHexApi::System::getGlobalScale()); + io.FontGlobalScale = 1.0 / ImHexApi::System::getContentScale(); // Load fonts necessary for the splash screen { @@ -512,7 +493,7 @@ namespace hex::init { ImFontConfig cfg; cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true; - cfg.SizePixels = ImHexApi::Fonts::DefaultFontSize; + cfg.SizePixels = ImHexApi::Fonts::DefaultFontSize * ImHexApi::System::getContentScale(); io.Fonts->AddFontDefault(&cfg); std::uint8_t *px; @@ -574,7 +555,7 @@ namespace hex::init { } void WindowSplash::exitGLFW() const { - glfwDestroyWindow(m_window); + hex::glfw::DestroyWindow(m_window); glfwTerminate(); } diff --git a/main/gui/source/window/linux_window.cpp b/main/gui/source/window/linux_window.cpp index 60fbbdd8e7e3b..309e6a609a474 100644 --- a/main/gui/source/window/linux_window.cpp +++ b/main/gui/source/window/linux_window.cpp @@ -11,6 +11,8 @@ #include #include + #include + #include #include @@ -18,7 +20,6 @@ #include #include - #include #include #include @@ -74,10 +75,6 @@ namespace hex { } void Window::configureGLFW() { - #if defined(GLFW_SCALE_FRAMEBUFFER) - glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE); - #endif - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_DECORATED, ImHexApi::System::isBorderlessWindowModeEnabled() ? GL_FALSE : GL_TRUE); @@ -140,7 +137,7 @@ namespace hex { }); glfwSetWindowRefreshCallback(m_window, [](GLFWwindow *window) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->fullFrame(); }); @@ -156,4 +153,4 @@ namespace hex { } -#endif \ No newline at end of file +#endif diff --git a/main/gui/source/window/macos_window.cpp b/main/gui/source/window/macos_window.cpp index 50d1b4c4d4dd1..ca766188cdbe8 100644 --- a/main/gui/source/window/macos_window.cpp +++ b/main/gui/source/window/macos_window.cpp @@ -11,11 +11,11 @@ #include #include + #include + #include #include - #include - namespace hex { void nativeErrorMessage(const std::string &message) { @@ -27,7 +27,6 @@ namespace hex { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE); glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); } @@ -99,7 +98,7 @@ namespace hex { setupMacosWindowStyle(m_window, ImHexApi::System::isBorderlessWindowModeEnabled()); glfwSetWindowRefreshCallback(m_window, [](GLFWwindow *window) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->fullFrame(); }); } diff --git a/main/gui/source/window/web_window.cpp b/main/gui/source/window/web_window.cpp index 827cf72f0b17a..0d5a44cc264fa 100644 --- a/main/gui/source/window/web_window.cpp +++ b/main/gui/source/window/web_window.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -119,7 +120,7 @@ namespace hex { }); glfwSetWindowRefreshCallback(m_window, [](GLFWwindow *window) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); resizeCanvas(); win->fullFrame(); }); diff --git a/main/gui/source/window/win_window.cpp b/main/gui/source/window/win_window.cpp index 4ff534fd3e682..d56caa369e51d 100644 --- a/main/gui/source/window/win_window.cpp +++ b/main/gui/source/window/win_window.cpp @@ -1,5 +1,4 @@ #include -#include #include "window.hpp" @@ -11,6 +10,7 @@ #include #include #include + #include #include #include @@ -48,22 +48,6 @@ namespace hex { // Custom Window procedure for receiving OS events static LRESULT commonWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { - case WM_DPICHANGED: { - int interfaceScaleSetting = int(hex::ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 0.0F) * 10.0F); - if (interfaceScaleSetting != 0) - break; - - const auto newScale = LOWORD(wParam) / 96.0F; - const auto oldScale = ImHexApi::System::getNativeScale(); - - EventDPIChanged::post(oldScale, newScale); - ImHexApi::System::impl::setNativeScale(newScale); - - ThemeManager::reapplyCurrentTheme(); - ImGui::GetStyle().ScaleAllSizes(newScale); - - return TRUE; - } case WM_COPYDATA: { // Handle opening files in existing instance @@ -390,18 +374,6 @@ namespace hex { void Window::initNative() { - // Setup DPI Awareness - { - using SetProcessDpiAwarenessContextFunc = HRESULT(WINAPI *)(DPI_AWARENESS_CONTEXT); - - SetProcessDpiAwarenessContextFunc SetProcessDpiAwarenessContext = - (SetProcessDpiAwarenessContextFunc)(void*)GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetProcessDpiAwarenessContext"); - - if (SetProcessDpiAwarenessContext != nullptr) { - SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - } - } - if (ImHexApi::System::isDebugBuild()) { // If the application is running in debug mode, ImHex runs under the CONSOLE subsystem, // so we don't need to do anything besides enabling ANSI colors @@ -629,12 +601,9 @@ namespace hex { ImGui::GetIO().ConfigDebugIsDebuggerPresent = ::IsDebuggerPresent(); - glfwSetFramebufferSizeCallback(m_window, [](GLFWwindow* window, int width, int height) { - auto *win = static_cast(glfwGetWindowUserPointer(window)); + hex::glfw::SetFramebufferSizeCallback(m_window, [](GLFWwindow* window, int, int) { + auto *win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->m_unlockFrameRate = true; - - glViewport(0, 0, width, height); - ImHexApi::System::impl::setMainWindowSize(width, height); }); DwmEnableMMCSS(TRUE); @@ -649,7 +618,7 @@ namespace hex { } glfwSetWindowRefreshCallback(m_window, [](GLFWwindow *window) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->fullFrame(); DwmFlush(); diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index 5e27102a858d9..dc922a5064f4f 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ #include #include +#include #include #include @@ -115,28 +117,13 @@ namespace hex { m_popupsToOpen.push_back(name); }); - EventDPIChanged::subscribe([this](float oldScaling, float newScaling) { - if (oldScaling == newScaling || oldScaling == 0 || newScaling == 0) - return; - - int width, height; - glfwGetWindowSize(m_window, &width, &height); - - width = float(width) * newScaling / oldScaling; - height = float(height) * newScaling / oldScaling; - - ImHexApi::System::impl::setMainWindowSize(width, height); - glfwSetWindowSize(m_window, width, height); - }); - - LayoutManager::registerLoadCallback([this](std::string_view line) { int width = 0, height = 0; sscanf(line.data(), "MainWindowSize=%d,%d", &width, &height); if (width > 0 && height > 0) { TaskManager::doLater([width, height, this]{ - glfwSetWindowSize(m_window, width, height); + hex::glfw::SetWindowSize(m_window, width, height); }); } }); @@ -218,8 +205,8 @@ namespace hex { { int x = 0, y = 0; int width = 0, height = 0; - glfwGetWindowPos(m_window, &x, &y); - glfwGetWindowSize(m_window, &width, &height); + hex::glfw::GetWindowPos(m_window, &x, &y); + hex::glfw::GetWindowSize(m_window, &width, &height); ImHexApi::System::impl::setMainWindowPosition(x, y); ImHexApi::System::impl::setMainWindowSize(width, height); @@ -265,10 +252,10 @@ namespace hex { static ImVec2 lastWindowSize = ImHexApi::System::getMainWindowSize(); if (ImHexApi::System::impl::isWindowResizable()) { - glfwSetWindowSizeLimits(m_window, 480_scaled, 360_scaled, GLFW_DONT_CARE, GLFW_DONT_CARE); + hex::glfw::SetWindowSizeLimits(m_window, 480, 360, GLFW_DONT_CARE, GLFW_DONT_CARE); lastWindowSize = ImHexApi::System::getMainWindowSize(); } else { - glfwSetWindowSizeLimits(m_window, lastWindowSize.x, lastWindowSize.y, lastWindowSize.x, lastWindowSize.y); + hex::glfw::SetWindowSizeLimits(m_window, lastWindowSize.x, lastWindowSize.y, lastWindowSize.x, lastWindowSize.y); } this->fullFrame(); @@ -779,11 +766,7 @@ namespace hex { // Create window m_windowTitle = "ImHex"; - m_window = glfwCreateWindow(1280_scaled, 720_scaled, m_windowTitle.c_str(), nullptr, nullptr); - - ImHexApi::System::impl::setMainWindowHandle(m_window); - - glfwSetWindowUserPointer(m_window, this); + m_window = hex::glfw::CreateWindow(1280, 720, m_windowTitle.c_str(), nullptr, nullptr); if (m_window == nullptr) { log::fatal("Failed to create window!"); @@ -793,6 +776,9 @@ namespace hex { // Force window to be fully opaque by default glfwSetWindowOpacity(m_window, 1.0F); + ImHexApi::System::impl::setMainWindowHandle(m_window); + hex::glfw::SetWindowUserPointer(m_window, this); + glfwMakeContextCurrent(m_window); // Disable VSync. Not like any graphics driver actually cares @@ -801,58 +787,60 @@ namespace hex { // Center window GLFWmonitor *monitor = glfwGetPrimaryMonitor(); if (monitor != nullptr) { - const GLFWvidmode *mode = glfwGetVideoMode(monitor); - if (mode != nullptr) { + int monitorWidth, monitorHeight; + if (hex::glfw::GetMonitorSize(monitor, &monitorWidth, &monitorHeight)) { int monitorX, monitorY; - glfwGetMonitorPos(monitor, &monitorX, &monitorY); + hex::glfw::GetMonitorPos(monitor, &monitorX, &monitorY); int windowWidth, windowHeight; - glfwGetWindowSize(m_window, &windowWidth, &windowHeight); + hex::glfw::GetWindowSize(m_window, &windowWidth, &windowHeight); - glfwSetWindowPos(m_window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2); + hex::glfw::SetWindowPos(m_window, monitorX + (monitorWidth - windowWidth) / 2, monitorY + (monitorHeight - windowHeight) / 2); } } // Set up initial window position { int x = 0, y = 0; - glfwGetWindowPos(m_window, &x, &y); if (initialWindowProperties.has_value()) { x = initialWindowProperties->x; y = initialWindowProperties->y; + } else { + hex::glfw::GetWindowPos(m_window, &x, &y); } ImHexApi::System::impl::setMainWindowPosition(x, y); - glfwSetWindowPos(m_window, x, y); + hex::glfw::SetWindowPos(m_window, x, y); } // Set up initial window size { int width = 0, height = 0; - glfwGetWindowSize(m_window, &width, &height); if (initialWindowProperties.has_value()) { width = initialWindowProperties->width; height = initialWindowProperties->height; + } else { + hex::glfw::GetWindowSize(m_window, &width, &height); } ImHexApi::System::impl::setMainWindowSize(width, height); - glfwSetWindowSize(m_window, width, height); + hex::glfw::SetWindowSize(m_window, width, height); } // Register window move callback - glfwSetWindowPosCallback(m_window, [](GLFWwindow *window, int x, int y) { + hex::glfw::SetWindowPosCallback(m_window, [](GLFWwindow *window, int x, int y) { ImHexApi::System::impl::setMainWindowPosition(x, y); - auto win = static_cast(glfwGetWindowUserPointer(window)); + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->m_unlockFrameRate = true; win->fullFrame(); }); // Register window resize callback - glfwSetWindowSizeCallback(m_window, [](GLFWwindow *window, [[maybe_unused]] int width, [[maybe_unused]] int height) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + hex::glfw::SetWindowSizeCallback(m_window, [](GLFWwindow *window, [[maybe_unused]] int width, [[maybe_unused]] int height) { + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->m_unlockFrameRate = true; #if !defined(OS_WINDOWS) @@ -870,8 +858,8 @@ namespace hex { #endif }); - glfwSetCursorPosCallback(m_window, [](GLFWwindow *window, double, double) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + hex::glfw::SetCursorPosCallback(m_window, [](GLFWwindow *window, double, double) { + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->m_unlockFrameRate = true; }); @@ -909,7 +897,7 @@ namespace hex { key != GLFW_KEY_LEFT_SHIFT && key != GLFW_KEY_RIGHT_SHIFT && key != GLFW_KEY_LEFT_SUPER && key != GLFW_KEY_RIGHT_SUPER ) { - auto win = static_cast(glfwGetWindowUserPointer(window)); + auto win = static_cast(hex::glfw::GetWindowUserPointer(window)); win->m_unlockFrameRate = true; if (!(mods & GLFW_MOD_NUM_LOCK)) { @@ -935,11 +923,27 @@ namespace hex { EventWindowClosing::post(window); }); - glfwSetWindowSizeLimits(m_window, 480_scaled, 360_scaled, GLFW_DONT_CARE, GLFW_DONT_CARE); + hex::glfw::SetWindowContentScaleCallback(m_window, [](GLFWwindow *window, float newScale, float) { + auto oldScale = ImHexApi::System::getContentScale(); + if (newScale == 0 || oldScale == newScale) + return; + + ImHexApi::System::impl::setContentScale(newScale); + + int width, height; + hex::glfw::GetWindowSize(window, &width, &height); + ImHexApi::System::impl::setMainWindowSize(width, height); + + ImGui::GetIO().FontGlobalScale = 1.0F / newScale; + EventDPIChanged::post(oldScale, newScale); + ThemeManager::reapplyCurrentTheme(); + }); + + hex::glfw::SetWindowSizeLimits(m_window, 480, 360, GLFW_DONT_CARE, GLFW_DONT_CARE); } void Window::resize(i32 width, i32 height) { - glfwSetWindowSize(m_window, width, height); + hex::glfw::SetWindowSize(m_window, width, height); } void Window::initImGui() { @@ -966,7 +970,6 @@ namespace hex { io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard; io.ConfigWindowsMoveFromTitleBarOnly = true; - io.FontGlobalScale = 1.0F; if (glfwGetPrimaryMonitor() != nullptr) { if (ImHexApi::System::isMutliWindowModeEnabled()) @@ -985,10 +988,6 @@ namespace hex { } io.UserData = &m_imguiCustomData; - - auto scale = ImHexApi::System::getGlobalScale(); - style.ScaleAllSizes(scale); - io.DisplayFramebufferScale = ImVec2(scale, scale); io.Fonts->SetTexID(fonts->TexID); style.WindowMenuButtonPosition = ImGuiDir_None; @@ -1041,10 +1040,19 @@ namespace hex { plugin.setImGuiContext(ImGui::GetCurrentContext()); RequestInitThemeHandlers::post(); + + { + float contentScale; + glfwGetWindowContentScale(m_window, &contentScale, nullptr); + ImHexApi::System::impl::setContentScale(contentScale); + } + + io.FontGlobalScale = 1.0F / ImHexApi::System::getContentScale(); + EventDPIChanged::post(ImHexApi::System::getContentScale(), ImHexApi::System::getContentScale()); } void Window::exitGLFW() { - glfwDestroyWindow(m_window); + hex::glfw::DestroyWindow(m_window); glfwTerminate(); m_window = nullptr; diff --git a/plugins/builtin/romfs/lang/de_DE.json b/plugins/builtin/romfs/lang/de_DE.json index 9308dd843c4e4..7babcdbdb4040 100644 --- a/plugins/builtin/romfs/lang/de_DE.json +++ b/plugins/builtin/romfs/lang/de_DE.json @@ -492,7 +492,6 @@ "hex.builtin.setting.interface.multi_windows": "Multi-Window-Unterstützung aktivieren", "hex.builtin.setting.interface.pattern_data_row_bg": "Aktiviere farbige Patternhintergründe", "hex.builtin.setting.interface.restore_window_pos": "Fensterposition und Grösse wiederherstellen", - "hex.builtin.setting.interface.scaling.native": "Nativ", "hex.builtin.setting.interface.scaling_factor": "Skalierung", "hex.builtin.setting.interface.show_header_command_palette": "Befehlspalette in Titelbar anzeigen", "hex.builtin.setting.interface.style": "Stil", diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index fbffa3bba9f32..95eb6bf97602b 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -501,7 +501,6 @@ "hex.builtin.setting.interface.language": "Language", "hex.builtin.setting.interface.multi_windows": "Enable Multi Window support", "hex.builtin.setting.interface.scaling_factor": "Scaling", - "hex.builtin.setting.interface.scaling.native": "Native", "hex.builtin.setting.interface.scaling.fractional_warning": "The default font does not support fractional scaling. For better results, select a custom font in the 'Font' tab.", "hex.builtin.setting.interface.show_header_command_palette": "Show Command Palette in Window Header", "hex.builtin.setting.interface.style": "Styling", diff --git a/plugins/builtin/romfs/lang/es_ES.json b/plugins/builtin/romfs/lang/es_ES.json index 09dee4ea72264..e4fe6238613de 100644 --- a/plugins/builtin/romfs/lang/es_ES.json +++ b/plugins/builtin/romfs/lang/es_ES.json @@ -489,7 +489,6 @@ "hex.builtin.setting.interface.multi_windows": "Activar soporte de ventanas múltiples", "hex.builtin.setting.interface.pattern_data_row_bg": "", "hex.builtin.setting.interface.restore_window_pos": "", - "hex.builtin.setting.interface.scaling.native": "Nativo", "hex.builtin.setting.interface.scaling_factor": "Escalado", "hex.builtin.setting.interface.style": "", "hex.builtin.setting.interface.wiki_explain_language": "Idioma de Wikipedia", diff --git a/plugins/builtin/romfs/lang/hu_HU.json b/plugins/builtin/romfs/lang/hu_HU.json index 644552553664d..d3ca464703dce 100644 --- a/plugins/builtin/romfs/lang/hu_HU.json +++ b/plugins/builtin/romfs/lang/hu_HU.json @@ -485,7 +485,6 @@ "hex.builtin.setting.interface.language": "Nyelv", "hex.builtin.setting.interface.multi_windows": "Több ablakos mód engedélyezése", "hex.builtin.setting.interface.scaling_factor": "Méretezés", - "hex.builtin.setting.interface.scaling.native": "Natív", "hex.builtin.setting.interface.show_header_command_palette": "Parancspaletta mutatása az ablak fejlécben", "hex.builtin.setting.interface.style": "Stílusok", "hex.builtin.setting.interface.window": "Ablak", diff --git a/plugins/builtin/romfs/lang/it_IT.json b/plugins/builtin/romfs/lang/it_IT.json index 55777ebe2d30c..4710e88b4c1cb 100644 --- a/plugins/builtin/romfs/lang/it_IT.json +++ b/plugins/builtin/romfs/lang/it_IT.json @@ -489,7 +489,6 @@ "hex.builtin.setting.interface.multi_windows": "", "hex.builtin.setting.interface.pattern_data_row_bg": "", "hex.builtin.setting.interface.restore_window_pos": "", - "hex.builtin.setting.interface.scaling.native": "Nativo", "hex.builtin.setting.interface.scaling_factor": "Scale", "hex.builtin.setting.interface.style": "", "hex.builtin.setting.interface.wiki_explain_language": "", diff --git a/plugins/builtin/romfs/lang/ja_JP.json b/plugins/builtin/romfs/lang/ja_JP.json index 92c6722ddd4b7..71c08b9d9d677 100644 --- a/plugins/builtin/romfs/lang/ja_JP.json +++ b/plugins/builtin/romfs/lang/ja_JP.json @@ -489,7 +489,6 @@ "hex.builtin.setting.interface.multi_windows": "", "hex.builtin.setting.interface.pattern_data_row_bg": "", "hex.builtin.setting.interface.restore_window_pos": "", - "hex.builtin.setting.interface.scaling.native": "ネイティブ", "hex.builtin.setting.interface.scaling_factor": "スケーリング", "hex.builtin.setting.interface.style": "", "hex.builtin.setting.interface.wiki_explain_language": "", diff --git a/plugins/builtin/romfs/lang/ko_KR.json b/plugins/builtin/romfs/lang/ko_KR.json index c201ab4a52884..8de596e545c49 100644 --- a/plugins/builtin/romfs/lang/ko_KR.json +++ b/plugins/builtin/romfs/lang/ko_KR.json @@ -489,7 +489,6 @@ "hex.builtin.setting.interface.multi_windows": "다중 창 지원 사용", "hex.builtin.setting.interface.pattern_data_row_bg": "색상 패턴 배경 사용", "hex.builtin.setting.interface.restore_window_pos": "창 위치 복원", - "hex.builtin.setting.interface.scaling.native": "기본", "hex.builtin.setting.interface.scaling_factor": "배율", "hex.builtin.setting.interface.style": "스타일", "hex.builtin.setting.interface.wiki_explain_language": "위키백과 언어", diff --git a/plugins/builtin/romfs/lang/pt_BR.json b/plugins/builtin/romfs/lang/pt_BR.json index ce60ad38f3c11..edbe96baada4f 100644 --- a/plugins/builtin/romfs/lang/pt_BR.json +++ b/plugins/builtin/romfs/lang/pt_BR.json @@ -489,7 +489,6 @@ "hex.builtin.setting.interface.multi_windows": "", "hex.builtin.setting.interface.pattern_data_row_bg": "", "hex.builtin.setting.interface.restore_window_pos": "", - "hex.builtin.setting.interface.scaling.native": "Nativo", "hex.builtin.setting.interface.scaling_factor": "Scaling", "hex.builtin.setting.interface.style": "", "hex.builtin.setting.interface.wiki_explain_language": "Idioma do Wikipedia", diff --git a/plugins/builtin/romfs/lang/zh_CN.json b/plugins/builtin/romfs/lang/zh_CN.json index af847367f038d..7c47ffca3cdeb 100644 --- a/plugins/builtin/romfs/lang/zh_CN.json +++ b/plugins/builtin/romfs/lang/zh_CN.json @@ -530,7 +530,6 @@ "hex.builtin.setting.interface.native_window_decorations": "使用操作系统窗口装饰", "hex.builtin.setting.interface.pattern_data_row_bg": "启用彩色图案背景", "hex.builtin.setting.interface.restore_window_pos": "恢复窗口位置", - "hex.builtin.setting.interface.scaling.native": "本地默认", "hex.builtin.setting.interface.scaling_factor": "缩放", "hex.builtin.setting.interface.show_header_command_palette": "在窗口标题中显示命令面板", "hex.builtin.setting.interface.style": "风格", diff --git a/plugins/builtin/romfs/lang/zh_TW.json b/plugins/builtin/romfs/lang/zh_TW.json index e80271fa4bc58..878f48018a709 100644 --- a/plugins/builtin/romfs/lang/zh_TW.json +++ b/plugins/builtin/romfs/lang/zh_TW.json @@ -489,7 +489,6 @@ "hex.builtin.setting.interface.multi_windows": "啟用多視窗支援", "hex.builtin.setting.interface.pattern_data_row_bg": "", "hex.builtin.setting.interface.restore_window_pos": "Restore window position", - "hex.builtin.setting.interface.scaling.native": "原生", "hex.builtin.setting.interface.scaling_factor": "縮放", "hex.builtin.setting.interface.style": "", "hex.builtin.setting.interface.wiki_explain_language": "維基百科語言", diff --git a/plugins/builtin/source/content/events.cpp b/plugins/builtin/source/content/events.cpp index 05e942b7eb340..1652b734cf2d3 100644 --- a/plugins/builtin/source/content/events.cpp +++ b/plugins/builtin/source/content/events.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -240,8 +241,8 @@ namespace hex::plugin::builtin { { int x = 0, y = 0, width = 0, height = 0, maximized = 0; - glfwGetWindowPos(window, &x, &y); - glfwGetWindowSize(window, &width, &height); + hex::glfw::GetWindowPos(window, &x, &y); + hex::glfw::GetWindowSize(window, &width, &height); maximized = glfwGetWindowAttrib(window, GLFW_MAXIMIZED); ContentRegistry::Settings::write("hex.builtin.setting.interface", "hex.builtin.setting.interface.window.x", x); diff --git a/plugins/builtin/source/content/init_tasks.cpp b/plugins/builtin/source/content/init_tasks.cpp index 55524504ae64e..46243ad1b2328 100644 --- a/plugins/builtin/source/content/init_tasks.cpp +++ b/plugins/builtin/source/content/init_tasks.cpp @@ -99,20 +99,18 @@ namespace hex::plugin::builtin { } bool configureUIScale() { - EventDPIChanged::subscribe([](float, float newScaling) { - int interfaceScaleSetting = int(ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 0.0F) * 10.0F); - - float interfaceScaling; - if (interfaceScaleSetting == 0) - interfaceScaling = newScaling; - else - interfaceScaling = interfaceScaleSetting / 10.0F; - - ImHexApi::System::impl::setGlobalScale(interfaceScaling); - }); - - const auto nativeScale = ImHexApi::System::getNativeScale(); - EventDPIChanged::post(nativeScale, nativeScale); + int interfaceScaleSetting = int(ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 1.0F) * 10.0F); + + float interfaceScaling; + // 0 used to mean 'native' but with DPI awareness in GLFW this just + // means no UI scaling + if (interfaceScaleSetting == 0) { + interfaceScaling = 1.0F; + ContentRegistry::Settings::write("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 1.0F); + } else + interfaceScaling = interfaceScaleSetting / 10.0F; + + ImHexApi::System::impl::setUserScale(interfaceScaling); return true; } diff --git a/plugins/builtin/source/content/main_menu_items.cpp b/plugins/builtin/source/content/main_menu_items.cpp index d917e31e1280b..caaf4050d7476 100644 --- a/plugins/builtin/source/content/main_menu_items.cpp +++ b/plugins/builtin/source/content/main_menu_items.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -536,11 +537,14 @@ namespace hex::plugin::builtin { size = ImHexApi::System::getMainWindowSize(); const auto monitor = glfwGetPrimaryMonitor(); - const auto videoMode = glfwGetVideoMode(monitor); - - glfwSetWindowMonitor(window, monitor, 0, 0, videoMode->width, videoMode->height, videoMode->refreshRate); + auto videoMode = glfwGetVideoMode(monitor); + if (videoMode) { + int monitorWidth, monitorHeight; + hex::glfw::GetMonitorSize(monitor, &monitorWidth, &monitorHeight); + hex::glfw::SetWindowMonitor(window, monitor, 0, 0, monitorWidth, monitorHeight, videoMode->refreshRate); + } } else { - glfwSetWindowMonitor(window, nullptr, position.x, position.y, size.x, size.y, 0); + hex::glfw::SetWindowMonitor(window, nullptr, position.x, position.y, size.x, size.y, 0); } }, []{ return true; }, []{ return glfwGetWindowMonitor(ImHexApi::System::getMainWindowHandle()) != nullptr; }); diff --git a/plugins/builtin/source/content/settings_entries.cpp b/plugins/builtin/source/content/settings_entries.cpp index 47500811a8bba..b41f10c482a2d 100644 --- a/plugins/builtin/source/content/settings_entries.cpp +++ b/plugins/builtin/source/content/settings_entries.cpp @@ -172,19 +172,16 @@ namespace hex::plugin::builtin { class ScalingWidget : public ContentRegistry::Settings::Widgets::Widget { public: bool draw(const std::string &name) override { - auto format = [this] -> std::string { - if (m_value == 0) - return "hex.builtin.setting.interface.scaling.native"_lang + hex::format(" (x{:.1f})", ImHexApi::System::getNativeScale()); - else - return "x%.1f"; + auto format = [] -> std::string { + return "x%.1f"; }(); - bool changed = ImGui::SliderFloat(name.data(), &m_value, 0, 4, format.c_str()); + bool changed = ImGui::SliderFloat(name.data(), &m_value, 0.1, 4, format.c_str()); - if (m_value < 0) - m_value = 0; - else if (m_value > 10) - m_value = 10; + if (m_value < 0.1) + m_value = 0.1; + else if (m_value > 4) + m_value = 4; if (s_showScalingWarning && (u32(m_value * 10) % 10) != 0) { ImGui::SameLine(); diff --git a/plugins/builtin/source/content/welcome_screen.cpp b/plugins/builtin/source/content/welcome_screen.cpp index 3a2ff1f1e82d2..320c13d156d29 100644 --- a/plugins/builtin/source/content/welcome_screen.cpp +++ b/plugins/builtin/source/content/welcome_screen.cpp @@ -557,7 +557,7 @@ namespace hex::plugin::builtin { for (const auto &path : paths::Config.read()) { if (auto crashFilePath = std::fs::path(path) / CrashFileName; wolv::io::fs::exists(crashFilePath)) { hasCrashed = true; - + log::info("Found crash.json file at {}", wolv::util::toUTF8String(crashFilePath)); wolv::io::File crashFile(crashFilePath, wolv::io::File::Mode::Read); nlohmann::json crashFileData; diff --git a/plugins/fonts/source/font_loader.cpp b/plugins/fonts/source/font_loader.cpp index 2ac7efb5e0bb7..b9eee16f915bb 100644 --- a/plugins/fonts/source/font_loader.cpp +++ b/plugins/fonts/source/font_loader.cpp @@ -380,7 +380,7 @@ namespace hex::fonts { ContentRegistry::Settings::write("hex.builtin.setting.font", "hex.builtin.setting.font.load_all_unicode_chars", false); ContentRegistry::Settings::write("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 1.0F); - ImHexApi::System::impl::setGlobalScale(1.0F); + ImHexApi::System::impl::setUserScale(1.0F); return false; } else {