improved font scaling text and window adjustment, added ctrl + scroll hotkey for font scaling

This commit is contained in:
2026-03-05 01:22:20 -06:00
parent 7d48936f30
commit eda19ef6d5
4 changed files with 183 additions and 101 deletions

View File

@@ -957,6 +957,10 @@ int main(int argc, char* argv[])
// resizing on a 200% screen doesn't clobber the 100% size.
std::map<int, std::pair<int,int>> savedSizeForScale;
bool dpiResizePending = false;
bool fontScaleResizePending = false;
// Font-scale window reference: size at scale 1.0 (updated on user resize)
float fontScaleRefFS = 0.0f;
int fontScaleRefW = 0, fontScaleRefH = 0;
// Track last known window size at the current DPI scale.
// Updated on user-initiated resizes (not DPI auto-resizes).
// When DISPLAY_SCALE_CHANGED fires, SDL_GetWindowSize() already
@@ -1140,7 +1144,28 @@ int main(int argc, char* argv[])
// Poll remaining events
SDL_Event event;
// Deferred font-scale commit: smooth visual update during Alt+scroll,
// atlas rebuild after scrolling stops (~200ms idle).
static Uint64 fontScaleCommitTick = 0; // 0 = nothing pending
while (SDL_PollEvent(&event)) {
// Alt + scroll wheel: smooth font scale adjustment
if (event.type == SDL_EVENT_MOUSE_WHEEL) {
SDL_Keymod mods = SDL_GetModState();
if (mods & SDL_KMOD_ALT) {
float step = 0.05f * event.wheel.y;
float cur = dragonx::ui::Layout::userFontScale();
float next = std::max(1.0f, std::min(1.5f, cur + step));
if (next != cur) {
// Smooth preview — no atlas rebuild yet
dragonx::ui::Layout::setUserFontScaleVisual(next);
// Schedule atlas rebuild after scrolling stops
fontScaleCommitTick = SDL_GetTicks() + 200;
}
// Don't pass Alt+scroll to ImGui (would scroll windows)
continue;
}
}
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT) {
@@ -1167,11 +1192,20 @@ int main(int argc, char* argv[])
bool isDpiResize = dpiResizePending ||
std::abs(actualScale - storedScale) > 0.01f;
if (dpiResizePending) dpiResizePending = false;
bool isFSResize = fontScaleResizePending;
if (fontScaleResizePending) fontScaleResizePending = false;
if (!isDpiResize) {
int pct = (int)lroundf(storedScale * 100.0f);
savedSizeForScale[pct] = {event.window.data1, event.window.data2};
lastKnownW = event.window.data1;
lastKnownH = event.window.data2;
// User manually resized — update the font-scale reference
// so the next scale change is relative to this size.
if (!isFSResize) {
float fs = dragonx::ui::Layout::userFontScale();
fontScaleRefW = (int)lroundf((float)event.window.data1 / fs);
fontScaleRefH = (int)lroundf((float)event.window.data2 / fs);
}
}
}
// Window restored from minimized — trigger immediate data refresh
@@ -1279,6 +1313,15 @@ int main(int argc, char* argv[])
// --- PerfLog: begin frame ---
dragonx::util::PerfLog::instance().beginFrame();
// Commit deferred font-scale change once scrolling has stopped.
if (fontScaleCommitTick != 0 && SDL_GetTicks() >= fontScaleCommitTick) {
fontScaleCommitTick = 0;
float fs = dragonx::ui::Layout::userFontScale();
dragonx::ui::Layout::setUserFontScale(fs);
app.settings()->setFontScale(fs);
app.settings()->save();
}
// Pre-frame: font atlas rebuilds and schema hot-reload must
// happen BEFORE NewFrame() because NewFrame() caches font ptrs.
app.preFrame();
@@ -1294,25 +1337,24 @@ int main(int argc, char* argv[])
}
// If font scale changed, resize window proportionally.
// anchorW/H = the window size at the moment the anchor was set.
// anchorFS = the font scale at that moment.
// target = anchorW * curFS / anchorFS (symmetric, no drift).
// Reference size (at scale 1.0) is updated on user-initiated resizes
// so the next scale change is relative to the current window, not a
// stale snapshot. target = ref * curFS — no rounding drift.
{
static float anchorFS = 0.0f;
static int anchorW = 0, anchorH = 0;
float curFS = dragonx::ui::Layout::userFontScale();
if (anchorFS < 0.001f) {
// First frame: the current window IS the reference for
// whatever font scale is loaded — no resize.
anchorFS = curFS;
SDL_GetWindowSize(window, &anchorW, &anchorH);
if (fontScaleRefFS < 0.001f) {
// First frame — record reference, no resize.
fontScaleRefFS = curFS;
int w, h;
SDL_GetWindowSize(window, &w, &h);
fontScaleRefW = (int)lroundf((float)w / curFS);
fontScaleRefH = (int)lroundf((float)h / curFS);
}
if (std::fabs(curFS - anchorFS) > 0.001f) {
float ratio = curFS / anchorFS;
int newW = (int)lroundf((float)anchorW * ratio);
int newH = (int)lroundf((float)anchorH * ratio);
if (std::fabs(curFS - fontScaleRefFS) > 0.001f) {
int newW = (int)lroundf((float)fontScaleRefW * curFS);
int newH = (int)lroundf((float)fontScaleRefH * curFS);
// Clamp to display work area
SDL_DisplayID did = SDL_GetDisplayForWindow(window);
@@ -1325,21 +1367,15 @@ int main(int argc, char* argv[])
}
float hwDpi = dragonx::ui::Layout::rawDpiScale();
// Update minimum size BEFORE resizing so the window can
// actually shrink when the font scale decreases.
SDL_SetWindowMinimumSize(window,
(int)(1024 * hwDpi * curFS),
(int)(720 * hwDpi * curFS));
(int)(1024 * hwDpi),
(int)(720 * hwDpi));
fontScaleResizePending = true;
SDL_SetWindowSize(window, newW, newH);
lastKnownW = newW;
lastKnownH = newH;
// Update anchor so we don't re-fire every frame.
// The new anchor becomes the current size/scale so
// subsequent slider movements are relative to here.
anchorW = newW;
anchorH = newH;
anchorFS = curFS;
fontScaleRefFS = curFS;
}
}