From 717b66c6602a1a59bb2de02b997d21935f424a51 Mon Sep 17 00:00:00 2001 From: andresdelcampo <33843515+andresdelcampo@users.noreply.github.com> Date: Fri, 29 Aug 2025 21:08:42 +0200 Subject: [PATCH 1/2] Fix Force 4:3 Aspect Ratio not working if Resizable window is enabled #6062 AI assisted fix, seems to work fine after a second iteration. Tested in WSL linux -a bit shaky to resize windows in this environment by default, but seems to behave fine now. --- src/qt/qt_mainwindow.cpp | 72 ++++++++++++++++++++++++++++++++++++++++ src/qt/qt_mainwindow.hpp | 1 + 2 files changed, 73 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 9ae180d1f..a5106e25c 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1016,11 +1016,71 @@ void MainWindow::updateShortcuts() ui->actionMute_Unmute->setShortcut(seq); } +void +MainWindow::adjustToForce43(int suggestedW, int suggestedH) +{ + // Only in resizable window mode with Force 4:3, and not fullscreen + if (!(vid_resize == 1 && force_43 > 0) || video_fullscreen) + return; + + static bool inAdjust = false; // prevent recursion + if (inAdjust) return; + inAdjust = true; + + // Make sure the render widget is allowed to stretch in resizable mode. + // (Normally this is done once via resizeContents, but that path is skipped in vid_resize==1.) + ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + + const int frameExtra = + menuBar()->height() + + (hide_status_bar ? 0 : statusBar()->height()) + + (hide_tool_bar ? 0 : ui->toolBar->height()); + + // Window size we’re trying to honor (may come from the QResizeEvent) + int winW = (suggestedW >= 0) ? suggestedW : width(); + int winH = (suggestedH >= 0) ? suggestedH : height(); + + // Work in logical pixels consistent with the rest of the file + const double dpr = (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.0); + int clientW = static_cast(winW / dpr); + int clientH = static_cast((winH - frameExtra) / dpr); + if (clientH < 1) clientH = 1; // safety + + // Fit a 4:3 box INSIDE the dragged rectangle + const int wForH = (clientH * 4) / 3; + const int hForW = (clientW * 3) / 4; + if (wForH <= clientW) clientW = wForH; else clientH = hForW; + + // Convert back to window size (device pixels + chrome) + const int newWinW = static_cast(clientW * dpr); + const int newWinH = static_cast(clientH * dpr) + frameExtra; + + if (newWinW != winW || newWinH != winH) + this->resize(newWinW, newWinH); + + // Keep the emulator’s notion of the requested screen size in sync + monitors[0].mon_scrnsz_x = clientW; + monitors[0].mon_scrnsz_y = clientH; + + // Notify both paths used elsewhere + ui->stackedWidget->onResize(width(), height()); // re-compute scale in the renderer + plat_resize_request(clientW, clientH, /*monitor_index=*/0); + + inAdjust = false; +} + void MainWindow::resizeEvent(QResizeEvent *event) { //qDebug() << pos().x() + event->size().width(); //qDebug() << pos().y() + event->size().height(); + + // Enforce 4:3 while dragging in resizable mode + if (vid_resize == 1 && force_43 > 0 && !video_fullscreen) { + adjustToForce43(event->size().width(), event->size().height()); + return; // we’ve already applied the corrected size & notified core + } + if (vid_resize == 1 || video_fullscreen) return; @@ -2075,6 +2135,18 @@ void MainWindow::on_actionForce_4_3_display_ratio_triggered() { video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43); + + if (vid_resize == 1 && !video_fullscreen) { + // Ensure the render widget can stretch in resizable mode + ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + if (force_43 > 0) { + // Snap to 4:3 now + adjustToForce43(); // uses current window size + } else { + // Turning OFF: reflow the renderer to current window size + ui->stackedWidget->onResize(width(), height()); + } + } } void diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 6a255ac85..cb336073f 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -176,6 +176,7 @@ private: std::unique_ptr status; std::shared_ptr mm; + void adjustToForce43(int suggestedW = -1, int suggestedH = -1); void updateShortcuts(); void processKeyboardInput(bool down, uint32_t keycode); #ifdef Q_OS_MACOS From ca429dd4930ff5878ea4ed79ef4708188844a88d Mon Sep 17 00:00:00 2001 From: andresdelcampo <33843515+andresdelcampo@users.noreply.github.com> Date: Sat, 30 Aug 2025 12:05:41 +0200 Subject: [PATCH 2/2] Run more iterations and retested Not fully sure this is much different from the previous solution, but proof of test working as expected. --- src/qt/qt_mainwindow.cpp | 101 ++++++++++++++++++++------------------- src/qt/qt_mainwindow.hpp | 4 +- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index a5106e25c..1c2e000ab 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -171,6 +171,8 @@ extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index); extern MainWindow *main_window; +bool MainWindow::s_adjustingForce43 = false; + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) @@ -1017,69 +1019,73 @@ void MainWindow::updateShortcuts() } void -MainWindow::adjustToForce43(int suggestedW, int suggestedH) +MainWindow::adjustForForce43(const QSize &newWinSize) { - // Only in resizable window mode with Force 4:3, and not fullscreen - if (!(vid_resize == 1 && force_43 > 0) || video_fullscreen) + // Only act in resizable mode with Force 4:3 enabled and not fullscreen + if (!(vid_resize == 1 && force_43 > 0) || video_fullscreen || s_adjustingForce43) return; - static bool inAdjust = false; // prevent recursion - if (inAdjust) return; - inAdjust = true; + s_adjustingForce43 = true; - // Make sure the render widget is allowed to stretch in resizable mode. - // (Normally this is done once via resizeContents, but that path is skipped in vid_resize==1.) - ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + // Height consumed by menu/status/toolbars + int chromeH = menuBar()->height() + + (hide_status_bar ? 0 : statusBar()->height()) + + (hide_tool_bar ? 0 : ui->toolBar->height()); - const int frameExtra = - menuBar()->height() + - (hide_status_bar ? 0 : statusBar()->height()) + - (hide_tool_bar ? 0 : ui->toolBar->height()); - - // Window size we’re trying to honor (may come from the QResizeEvent) - int winW = (suggestedW >= 0) ? suggestedW : width(); - int winH = (suggestedH >= 0) ? suggestedH : height(); - - // Work in logical pixels consistent with the rest of the file - const double dpr = (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.0); + // Compute client area size in device‑independent pixels + double dpr = (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.0); + int winW = newWinSize.width(); + int winH = newWinSize.height(); int clientW = static_cast(winW / dpr); - int clientH = static_cast((winH - frameExtra) / dpr); - if (clientH < 1) clientH = 1; // safety + int clientH = static_cast((winH - chromeH) / dpr); - // Fit a 4:3 box INSIDE the dragged rectangle - const int wForH = (clientH * 4) / 3; - const int hForW = (clientW * 3) / 4; - if (wForH <= clientW) clientW = wForH; else clientH = hForW; + if (clientW <= 0 || clientH <= 0) { + s_adjustingForce43 = false; + return; + } - // Convert back to window size (device pixels + chrome) - const int newWinW = static_cast(clientW * dpr); - const int newWinH = static_cast(clientH * dpr) + frameExtra; + // Decide which dimension the user changed most – adjust the other + int curW = static_cast(width() / dpr); + int curH = static_cast((height() - chromeH) / dpr); + bool widthChanged = std::abs(clientW - curW) >= std::abs(clientH - curH); - if (newWinW != winW || newWinH != winH) - this->resize(newWinW, newWinH); + int targetW, targetH; + if (widthChanged) { + // user dragged width – compute matching height for 4:3 + targetW = clientW; + targetH = (clientW * 3) / 4; + } else { + // user dragged height – compute matching width for 4:3 + targetH = clientH; + targetW = (clientH * 4) / 3; + } - // Keep the emulator’s notion of the requested screen size in sync - monitors[0].mon_scrnsz_x = clientW; - monitors[0].mon_scrnsz_y = clientH; + // Convert back to window size including chrome and apply + int newW = static_cast(targetW * dpr); + int newH = static_cast(targetH * dpr) + chromeH; + if (newW != winW || newH != winH) + resize(newW, newH); - // Notify both paths used elsewhere - ui->stackedWidget->onResize(width(), height()); // re-compute scale in the renderer - plat_resize_request(clientW, clientH, /*monitor_index=*/0); + // Update emulator framebuffer size and notify platform + monitors[0].mon_scrnsz_x = targetW; + monitors[0].mon_scrnsz_y = targetH; + plat_resize_request(targetW, targetH, 0); - inAdjust = false; + // Allow renderer widget to grow and recompute scaling + ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + ui->stackedWidget->onResize(width(), height()); + + s_adjustingForce43 = false; } - + void MainWindow::resizeEvent(QResizeEvent *event) { //qDebug() << pos().x() + event->size().width(); //qDebug() << pos().y() + event->size().height(); - // Enforce 4:3 while dragging in resizable mode - if (vid_resize == 1 && force_43 > 0 && !video_fullscreen) { - adjustToForce43(event->size().width(), event->size().height()); - return; // we’ve already applied the corrected size & notified core - } + // Enforce 4:3 aspect ratio in resizable mode when the option is set + adjustForForce43(event->size()); if (vid_resize == 1 || video_fullscreen) return; @@ -2136,14 +2142,13 @@ MainWindow::on_actionForce_4_3_display_ratio_triggered() { video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43); + // When turning on Force 4:3 in resizable mode, immediately snap to 4:3 if (vid_resize == 1 && !video_fullscreen) { - // Ensure the render widget can stretch in resizable mode ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); if (force_43 > 0) { - // Snap to 4:3 now - adjustToForce43(); // uses current window size + adjustForForce43(size()); } else { - // Turning OFF: reflow the renderer to current window size + // Turning off: refresh renderer scaling ui->stackedWidget->onResize(width(), height()); } } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index cb336073f..792685f42 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -176,7 +176,9 @@ private: std::unique_ptr status; std::shared_ptr mm; - void adjustToForce43(int suggestedW = -1, int suggestedH = -1); + static bool s_adjustingForce43; // guard against recursion + void adjustForForce43(const QSize &newWinSize); + void updateShortcuts(); void processKeyboardInput(bool down, uint32_t keycode); #ifdef Q_OS_MACOS