1
0
mirror of synced 2024-11-12 02:00:52 +01:00

impr: Further try to improve window resize flickering on Windows

This commit is contained in:
WerWolv 2024-06-29 23:17:59 +02:00
parent f90dc5d619
commit adc279d681
4 changed files with 70 additions and 4 deletions

View File

@ -60,7 +60,7 @@ target_compile_definitions(main PRIVATE IMHEX_PROJECT_NAME="${PROJECT_NAME}")
target_link_libraries(main PRIVATE libromfs-imhex libimhex libwolv ${LIBBACKTRACE_LIBRARIES} LLVMDemangle)
if (WIN32)
target_link_libraries(main PRIVATE usp10 wsock32 ws2_32 Dwmapi.lib)
target_link_libraries(main PRIVATE usp10 wsock32 ws2_32 Dwmapi.lib Winmm.lib)
else ()
target_link_libraries(main PRIVATE pthread)
endif ()

View File

@ -5,7 +5,7 @@
#include "messaging.hpp"
#include <hex/helpers/utils.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/default_paths.hpp>
@ -24,6 +24,7 @@
#include <wrl/client.h>
#include <fcntl.h>
#include <shellapi.h>
#include <timeapi.h>
#include <cstdio>
@ -160,7 +161,50 @@ namespace hex {
rect = client;
}
return 0;
// This code tries to avoid DWM flickering when resizing the window
// It's not perfect, but it's really the best we can do.
LARGE_INTEGER performanceFrequency = {};
QueryPerformanceFrequency(&performanceFrequency);
TIMECAPS tc = {};
timeGetDevCaps(&tc, sizeof(tc));
const auto granularity = tc.wPeriodMin;
timeBeginPeriod(tc.wPeriodMin);
DWM_TIMING_INFO dti = {};
dti.cbSize = sizeof(dti);
::DwmGetCompositionTimingInfo(nullptr, &dti);
LARGE_INTEGER end = {};
QueryPerformanceCounter(&end);
const auto period = dti.qpcRefreshPeriod;
const i64 delta = dti.qpcVBlank - end.QuadPart;
i64 sleepTicks = 0;
i64 sleepMilliSeconds = 0;
if (delta >= 0) {
sleepTicks = delta / period;
} else {
sleepTicks = -1 + delta / period;
}
sleepMilliSeconds = delta - (period * sleepTicks);
const double sleepTime = (1000.0 * double(sleepMilliSeconds) / double(performanceFrequency.QuadPart));
Sleep(DWORD(std::round(sleepTime)));
timeEndPeriod(granularity);
return WVR_REDRAW;
}
case WM_ERASEBKGND:
return 1;
case WM_WINDOWPOSCHANGING: {
// Make sure that windows discards the entire client area when resizing to avoid flickering
const auto windowPos = reinterpret_cast<LPWINDOWPOS>(lParam);
windowPos->flags |= SWP_NOCOPYBITS;
break;
}
case WM_NCHITTEST: {
// Handle window resizing and moving
@ -562,8 +606,20 @@ namespace hex {
ImHexApi::System::impl::setMainWindowSize(width, height);
});
DwmEnableMMCSS(TRUE);
{
constexpr BOOL value = TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_ENABLED, &value, sizeof(value));
}
{
constexpr DWMNCRENDERINGPOLICY value = DWMNCRP_ENABLED;
DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &value, sizeof(value));
}
glfwSetWindowRefreshCallback(m_window, [](GLFWwindow *window) {
auto win = static_cast<Window *>(glfwGetWindowUserPointer(window));
win->fullFrame();
DwmFlush();
});

View File

@ -194,6 +194,16 @@ namespace hex {
while (!glfwWindowShouldClose(m_window)) {
m_lastStartFrameTime = glfwGetTime();
{
int x = 0, y = 0;
int width = 0, height = 0;
glfwGetWindowPos(m_window, &x, &y);
glfwGetWindowSize(m_window, &width, &height);
ImHexApi::System::impl::setMainWindowPosition(x, y);
ImHexApi::System::impl::setMainWindowSize(width, height);
}
// Determine if the application should be in long sleep mode
bool shouldLongSleep = !m_unlockFrameRate;

View File

@ -146,7 +146,7 @@ namespace hex::plugin::builtin {
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered));
const auto windowSize = ImHexApi::System::getMainWindowSize();
const auto windowSize = ImGui::GetWindowSize();
auto searchBoxSize = ImVec2(s_showSearchBar ? windowSize.x / 2.5 : ImGui::CalcTextSize(s_windowTitle.c_str()).x, titleBarHeight);
auto searchBoxPos = ImVec2((windowSize / 2 - searchBoxSize / 2).x, 0);
auto titleBarButtonPosY = 0.0F;