From 962137fcdf56d969ffab2dfb8c3cae923aa7fd3d Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 20 Dec 2025 15:05:35 +1000 Subject: [PATCH] Qt: Move some settings around Need the extra space. --- src/core/fullscreenui_settings.cpp | 96 ++++++++++--------- src/core/fullscreenui_strings.h | 5 +- src/duckstation-qt/advancedsettingswidget.cpp | 15 --- src/duckstation-qt/graphicssettingswidget.cpp | 33 +++---- src/duckstation-qt/graphicssettingswidget.ui | 51 +++++----- .../interfacesettingswidget.cpp | 59 +++++++++--- src/duckstation-qt/interfacesettingswidget.h | 4 +- src/duckstation-qt/interfacesettingswidget.ui | 33 +++++-- src/duckstation-qt/qtutils.h | 11 +++ .../resources/duckstation-qt.qrc | 2 + .../icons/black/svg/chat-history-line.svg | 1 + .../icons/white/svg/chat-history-line.svg | 1 + src/duckstation-qt/settingswindow.h | 2 +- 13 files changed, 183 insertions(+), 130 deletions(-) create mode 100644 src/duckstation-qt/resources/icons/black/svg/chat-history-line.svg create mode 100644 src/duckstation-qt/resources/icons/white/svg/chat-history-line.svg diff --git a/src/core/fullscreenui_settings.cpp b/src/core/fullscreenui_settings.cpp index 671dd83b9..fe64b120c 100644 --- a/src/core/fullscreenui_settings.cpp +++ b/src/core/fullscreenui_settings.cpp @@ -112,7 +112,7 @@ static u32 GetEffectiveUIntSetting(SettingsInterface* bsi, const char* section, static float GetEffectiveFloatSetting(SettingsInterface* bsi, const char* section, const char* key, float default_value); static TinyString GetEffectiveTinyStringSetting(SettingsInterface* bsi, const char* section, const char* key, - const char* default_value); + const char* default_value = ""); static void BeginResetSettings(); static void DoCopyGameSettings(); static void DoClearGameSettings(); @@ -2223,6 +2223,12 @@ void FullscreenUI::DrawInterfaceSettingsPage() DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_ARROW_POINTER, "Hide Cursor In Fullscreen"), FSUI_VSTR("Hides the mouse pointer/cursor when the emulator is in fullscreen mode."), "Main", "HideCursorInFullscreen", true); + DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_MINIMIZE, "Disable Window Resizing"), + FSUI_VSTR("Prevents resizing of the window while a game is running."), "Main", + "DisableWindowResize", false); + DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_MAXIMIZE, "Automatically Resize Window"), + FSUI_VSTR("Automatically resizes the window to match the internal resolution."), "Display", + "AutoResizeWindow", false); MenuHeading(FSUI_VSTR("On-Screen Display")); DrawIntSpinBoxSetting(bsi, FSUI_ICONVSTR(ICON_FA_MAGNIFYING_GLASS, "OSD Scale"), @@ -3792,6 +3798,21 @@ void FullscreenUI::DrawGraphicsSettingsPage() DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_SITEMAP, "PGXP Depth Buffer"), FSUI_VSTR("Reduces polygon Z-fighting through depth testing. Low compatibility with games."), "GPU", "PGXPDepthBuffer", false, pgxp_enabled && texture_correction_enabled); + + const GPUTextureFilter texture_filtering = + Settings::ParseTextureFilterName(GetEffectiveTinyStringSetting(bsi, "GPU", "TextureFilter")) + .value_or(Settings::DEFAULT_GPU_TEXTURE_FILTER); + const GPUTextureFilter sprite_texture_filtering = + Settings::ParseTextureFilterName(GetEffectiveTinyStringSetting(bsi, "GPU", "SpriteTextureFilter")) + .value_or(texture_filtering); + + DrawToggleSetting( + bsi, FSUI_ICONVSTR(ICON_FA_EYE_DROPPER, "Round Upscaled Texture Coordinates"), + FSUI_VSTR("Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned " + "textures in some games, but break others, and is incompatible with texture filtering."), + "GPU", "ForceRoundTextureCoordinates", false, + resolution_scale != 1 && + (texture_filtering == GPUTextureFilter::Nearest || sprite_texture_filtering == GPUTextureFilter::Nearest)); } DrawToggleSetting( @@ -3803,7 +3824,7 @@ void FullscreenUI::DrawGraphicsSettingsPage() FSUI_VSTR("Smooths out blockyness between colour transitions in 24-bit content, usually FMVs."), "GPU", "ChromaSmoothing24Bit", false); - MenuHeading(FSUI_VSTR("Advanced")); + MenuHeading(FSUI_VSTR("Advanced Display Options")); std::optional strvalue = bsi->GetOptionalSmallStringValue( "GPU", "FullscreenMode", game_settings ? std::nullopt : std::optional("")); @@ -3897,49 +3918,6 @@ void FullscreenUI::DrawGraphicsSettingsPage() std::numeric_limits::max(), "%dpx"); } - if (is_hardware) - { - DrawEnumSetting(bsi, FSUI_ICONVSTR(ICON_FA_GRIP_LINES_VERTICAL, "Line Detection"), - FSUI_VSTR("Attempts to detect one pixel high/wide lines that rely on non-upscaled rasterization " - "behavior, filling in gaps introduced by upscaling."), - "GPU", "LineDetectMode", Settings::DEFAULT_GPU_LINE_DETECT_MODE, &Settings::ParseLineDetectModeName, - &Settings::GetLineDetectModeName, &Settings::GetLineDetectModeDisplayName, GPULineDetectMode::Count, - resolution_scale > 1); - - DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_DROPLET_SLASH, "Scaled Interlacing"), - FSUI_VSTR("Scales line skipping in interlaced rendering to the internal resolution, making it " - "less noticeable. Usually safe to enable."), - "GPU", "ScaledInterlacing", true, resolution_scale > 1); - - const GPUTextureFilter texture_filtering = - Settings::ParseTextureFilterName( - GetEffectiveTinyStringSetting(bsi, "GPU", "TextureFilter", - Settings::GetTextureFilterName(Settings::DEFAULT_GPU_TEXTURE_FILTER))) - .value_or(Settings::DEFAULT_GPU_TEXTURE_FILTER); - - DrawToggleSetting( - bsi, FSUI_ICONVSTR(ICON_FA_EYE_DROPPER, "Round Upscaled Texture Coordinates"), - FSUI_VSTR("Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned " - "textures in some games, but break others, and is incompatible with texture filtering."), - "GPU", "ForceRoundTextureCoordinates", false, - resolution_scale > 1 && texture_filtering == GPUTextureFilter::Nearest); - - DrawToggleSetting( - bsi, FSUI_ICONVSTR(ICON_FA_DOWNLOAD, "Use Software Renderer For Readbacks"), - FSUI_VSTR("Runs the software renderer in parallel for VRAM readbacks. On some systems, this may result in " - "greater performance when using graphical enhancements with the hardware renderer."), - "GPU", "UseSoftwareRendererForReadbacks", false); - } - - DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_BOLT, "Threaded Rendering"), - FSUI_VSTR("Uses a second thread for drawing graphics. Provides a significant speed improvement " - "particularly with the software renderer, and is safe to use."), - "GPU", "UseThread", true); - - DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_ARROWS_UP_DOWN_LEFT_RIGHT, "Automatically Resize Window"), - FSUI_VSTR("Automatically resizes the window to match the internal resolution."), "Display", - "AutoResizeWindow", false); - DrawToggleSetting( bsi, FSUI_ICONVSTR(ICON_FA_ENVELOPE, "Disable Mailbox Presentation"), FSUI_VSTR("Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. " @@ -3956,6 +3934,34 @@ void FullscreenUI::DrawGraphicsSettingsPage() } #endif + MenuHeading(FSUI_VSTR("Advanced Rendering Options")); + + if (is_hardware) + { + DrawEnumSetting(bsi, FSUI_ICONVSTR(ICON_FA_GRIP_LINES_VERTICAL, "Line Detection"), + FSUI_VSTR("Attempts to detect one pixel high/wide lines that rely on non-upscaled rasterization " + "behavior, filling in gaps introduced by upscaling."), + "GPU", "LineDetectMode", Settings::DEFAULT_GPU_LINE_DETECT_MODE, &Settings::ParseLineDetectModeName, + &Settings::GetLineDetectModeName, &Settings::GetLineDetectModeDisplayName, GPULineDetectMode::Count, + resolution_scale > 1); + + DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_DROPLET_SLASH, "Scaled Interlacing"), + FSUI_VSTR("Scales line skipping in interlaced rendering to the internal resolution, making it " + "less noticeable. Usually safe to enable."), + "GPU", "ScaledInterlacing", true, resolution_scale > 1); + + DrawToggleSetting( + bsi, FSUI_ICONVSTR(ICON_FA_DOWNLOAD, "Use Software Renderer For Readbacks"), + FSUI_VSTR("Runs the software renderer in parallel for VRAM readbacks. On some systems, this may result in " + "greater performance when using graphical enhancements with the hardware renderer."), + "GPU", "UseSoftwareRendererForReadbacks", false); + } + + DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_BOLT, "Threaded Rendering"), + FSUI_VSTR("Uses a second thread for drawing graphics. Provides a significant speed improvement " + "particularly with the software renderer, and is safe to use."), + "GPU", "UseThread", true); + if (is_hardware && pgxp_enabled) { MenuHeading(FSUI_VSTR("PGXP (Precision Geometry Transform Pipeline)")); diff --git a/src/core/fullscreenui_strings.h b/src/core/fullscreenui_strings.h index dc3aced93..d1ecbc423 100644 --- a/src/core/fullscreenui_strings.h +++ b/src/core/fullscreenui_strings.h @@ -103,7 +103,8 @@ TRANSLATE_NOOP("FullscreenUI", "Adds a new directory to the game search list."); TRANSLATE_NOOP("FullscreenUI", "Adds a new shader to the chain."); TRANSLATE_NOOP("FullscreenUI", "Adds additional precision to PGXP data post-projection. May improve visuals in some games."); TRANSLATE_NOOP("FullscreenUI", "Adjusts the emulation speed so the console's refresh rate matches the host when VSync is enabled."); -TRANSLATE_NOOP("FullscreenUI", "Advanced"); +TRANSLATE_NOOP("FullscreenUI", "Advanced Display Options"); +TRANSLATE_NOOP("FullscreenUI", "Advanced Rendering Options"); TRANSLATE_NOOP("FullscreenUI", "Advanced Settings"); TRANSLATE_NOOP("FullscreenUI", "All Time: {}"); TRANSLATE_NOOP("FullscreenUI", "Allow Booting Without SBI File"); @@ -264,6 +265,7 @@ TRANSLATE_NOOP("FullscreenUI", "Device Settings"); TRANSLATE_NOOP("FullscreenUI", "Disable Mailbox Presentation"); TRANSLATE_NOOP("FullscreenUI", "Disable Speedup on MDEC"); TRANSLATE_NOOP("FullscreenUI", "Disable Subdirectory Scanning"); +TRANSLATE_NOOP("FullscreenUI", "Disable Window Resizing"); TRANSLATE_NOOP("FullscreenUI", "Disable on 2D Polygons"); TRANSLATE_NOOP("FullscreenUI", "Disabled"); TRANSLATE_NOOP("FullscreenUI", "Disc"); @@ -553,6 +555,7 @@ TRANSLATE_NOOP("FullscreenUI", "Preload Replacement Textures"); TRANSLATE_NOOP("FullscreenUI", "Preserve Projection Precision"); TRANSLATE_NOOP("FullscreenUI", "Press To Toggle"); TRANSLATE_NOOP("FullscreenUI", "Pressure"); +TRANSLATE_NOOP("FullscreenUI", "Prevents resizing of the window while a game is running."); TRANSLATE_NOOP("FullscreenUI", "Prevents the emulator from producing any audible sound."); TRANSLATE_NOOP("FullscreenUI", "Prevents the screen saver from activating and the host from sleeping while emulation is running."); TRANSLATE_NOOP("FullscreenUI", "Progress Indicators"); diff --git a/src/duckstation-qt/advancedsettingswidget.cpp b/src/duckstation-qt/advancedsettingswidget.cpp index 1b6c178c3..d98f0e6d9 100644 --- a/src/duckstation-qt/advancedsettingswidget.cpp +++ b/src/duckstation-qt/advancedsettingswidget.cpp @@ -265,14 +265,6 @@ void AdvancedSettingsWidget::addTweakOptions() static_cast(SaveStateCompressionMode::Count), Settings::DEFAULT_SAVE_STATE_COMPRESSION_MODE); -#if defined(_WIN32) - addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Disable Window Rounded Corners"), "Main", - "DisableWindowRoundedCorners", false); -#elif defined(__APPLE__) - addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Use Fractional Window Scale"), "Main", - "UseFractionalWindowScale", true); -#endif - if (m_dialog->isPerGameSettings()) { addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display Active Start Offset"), "Display", @@ -345,11 +337,6 @@ void AdvancedSettingsWidget::onResetToDefaultClicked() setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Load Devices From Save States setChoiceTweakOption(m_ui.tweakOptionTable, i++, Settings::DEFAULT_SAVE_STATE_COMPRESSION_MODE); // Save State Compression -#if defined(_WIN32) - setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Disable Window Rounded Corners -#elif defined(__APPLE__) - setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Use Fractional Rendering Scale -#endif setIntRangeTweakOption(m_ui.tweakOptionTable, i++, static_cast(Settings::DEFAULT_DMA_MAX_SLICE_TICKS)); // DMA max slice ticks setIntRangeTweakOption(m_ui.tweakOptionTable, i++, @@ -390,8 +377,6 @@ void AdvancedSettingsWidget::onResetToDefaultClicked() sif->DeleteValue("Main", "ApplyCompatibilitySettings"); sif->DeleteValue("Main", "LoadDevicesFromSaveStates"); sif->DeleteValue("Main", "CompressSaveStates"); - sif->DeleteValue("Main", "DisableWindowRoundedCorners"); - sif->DeleteValue("Main", "UseFractionalWindowScale"); sif->DeleteValue("Display", "ActiveStartOffset"); sif->DeleteValue("Display", "ActiveEndOffset"); sif->DeleteValue("Display", "LineStartOffset"); diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index 57075d7ff..7d5304fb6 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -100,11 +100,15 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pgxpDepthBuffer, "GPU", "PGXPDepthBuffer", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.force43For24Bit, "Display", "Force4_3For24Bit", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.chromaSmoothingFor24Bit, "GPU", "ChromaSmoothing24Bit", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.forceRoundedTexcoords, "GPU", "ForceRoundTextureCoordinates", + false); connect(m_ui.renderer, QOverload::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::updateRendererDependentOptions); connect(m_ui.textureFiltering, QOverload::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::updateResolutionDependentOptions); + connect(m_ui.spriteTextureFiltering, QOverload::of(&QComboBox::currentIndexChanged), this, + &GraphicsSettingsWidget::updateResolutionDependentOptions); connect(m_ui.gpuDownsampleMode, QOverload::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onDownsampleModeChanged); connect(m_ui.pgxpEnable, &QCheckBox::checkStateChanged, this, &GraphicsSettingsWidget::updatePGXPSettingsEnabled); @@ -149,8 +153,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.displayFineCropBottom, "Display", "FineCropBottom", 0); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableMailboxPresentation, "Display", "DisableMailboxPresentation", false); - SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.automaticallyResizeWindow, "Display", "AutoResizeWindow", - false); #ifdef _WIN32 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.blitSwapChain, "Display", "UseBlitSwapChain", false); #endif @@ -164,8 +166,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.scaledInterlacing, "GPU", "ScaledInterlacing", true); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useSoftwareRendererForReadbacks, "GPU", "UseSoftwareRendererForReadbacks", false); - SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.forceRoundedTexcoords, "GPU", "ForceRoundTextureCoordinates", - false); connect(m_ui.displayFineCropMode, QOverload::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onFineCropModeChanged); @@ -389,7 +389,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* updateRendererDependentOptions(); onDownsampleModeChanged(); onFineCropModeChanged(); - updateResolutionDependentOptions(); onOSDShowMessagesChanged(); onMediaCaptureBackendChanged(); onMediaCaptureAudioEnabledChanged(); @@ -479,6 +478,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* tr("Switches back to 4:3 display aspect ratio when displaying 24-bit content, usually FMVs.")); dialog->registerWidgetHelp(m_ui.chromaSmoothingFor24Bit, tr("FMV Chroma Smoothing"), tr("Unchecked"), tr("Smooths out blockyness between colour transitions in 24-bit content, usually FMVs.")); + dialog->registerWidgetHelp( + m_ui.forceRoundedTexcoords, tr("Round Upscaled Texture Coordinates"), tr("Unchecked"), + tr("Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned textures in some games, but " + "break others, and is incompatible with texture filtering.")); // Advanced Tab @@ -497,9 +500,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* m_ui.disableMailboxPresentation, tr("Disable Mailbox Presentation"), tr("Unchecked"), tr("Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. " "Usually results in worse frame pacing.")); - dialog->registerWidgetHelp(m_ui.automaticallyResizeWindow, tr("Automatically Resize Window"), tr("Unchecked"), - tr("Automatically resizes the window to match the internal resolution. For high " - "internal resolutions, this will create very large windows.")); #ifdef _WIN32 dialog->registerWidgetHelp(m_ui.blitSwapChain, tr("Use Blit Swap Chain"), tr("Unchecked"), tr("Uses a blit presentation model instead of flipping when using the Direct3D 11 " @@ -526,10 +526,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* m_ui.useSoftwareRendererForReadbacks, tr("Software Renderer Readbacks"), tr("Unchecked"), tr("Runs the software renderer in parallel for VRAM readbacks. On some systems, this may result in greater " "performance when using graphical enhancements with the hardware renderer.")); - dialog->registerWidgetHelp( - m_ui.forceRoundedTexcoords, tr("Round Upscaled Texture Coordinates"), tr("Unchecked"), - tr("Rounds texture coordinates instead of flooring when upscaling. Can fix misaligned textures in some games, but " - "break others, and is incompatible with texture filtering.")); // PGXP Tab @@ -825,6 +821,7 @@ void GraphicsSettingsWidget::updateRendererDependentOptions() populateGPUAdaptersAndResolutions(render_api); updatePGXPSettingsEnabled(); + updateResolutionDependentOptions(); } void GraphicsSettingsWidget::populateGPUAdaptersAndResolutions(RenderAPI render_api) @@ -1143,14 +1140,14 @@ void GraphicsSettingsWidget::updateResolutionDependentOptions() const bool is_hardware = (getEffectiveRenderer() != GPURenderer::Software); const int scale = m_dialog->getEffectiveIntValue("GPU", "ResolutionScale", 1); const GPUTextureFilter texture_filtering = - Settings::ParseTextureFilterName( - m_dialog - ->getEffectiveStringValue("GPU", "TextureFilter", - Settings::GetTextureFilterName(Settings::DEFAULT_GPU_TEXTURE_FILTER)) - .c_str()) + Settings::ParseTextureFilterName(m_dialog->getEffectiveStringValue("GPU", "TextureFilter").c_str()) .value_or(Settings::DEFAULT_GPU_TEXTURE_FILTER); + const GPUTextureFilter sprite_texture_filtering = + Settings::ParseTextureFilterName(m_dialog->getEffectiveStringValue("GPU", "SpriteTextureFilter").c_str()) + .value_or(texture_filtering); m_ui.forceRoundedTexcoords->setEnabled( - is_hardware && scale > 1 && texture_filtering == GPUTextureFilter::Nearest && + is_hardware && scale != 1 && + (texture_filtering == GPUTextureFilter::Nearest || sprite_texture_filtering == GPUTextureFilter::Nearest) && !m_dialog->hasGameTrait(GameDatabase::Trait::ForceRoundUpscaledTextureCoordinates)); } diff --git a/src/duckstation-qt/graphicssettingswidget.ui b/src/duckstation-qt/graphicssettingswidget.ui index f9cbd1fc5..8a075cb75 100644 --- a/src/duckstation-qt/graphicssettingswidget.ui +++ b/src/duckstation-qt/graphicssettingswidget.ui @@ -274,6 +274,13 @@ + + + + Round Upscaled Texture Coordinates + + + @@ -475,33 +482,19 @@ - - - Automatically Resize Window - - - - Disable Mailbox Presentation - + Use Blit Swap Chain - - - - Software Renderer Readbacks - - - @@ -535,20 +528,6 @@ - - - - Scaled Interlacing - - - - - - - Round Upscaled Texture Coordinates - - - @@ -574,6 +553,20 @@ + + + + Software Renderer Readbacks + + + + + + + Scaled Interlacing + + + diff --git a/src/duckstation-qt/interfacesettingswidget.cpp b/src/duckstation-qt/interfacesettingswidget.cpp index 138edd2f2..93e0a01f4 100644 --- a/src/duckstation-qt/interfacesettingswidget.cpp +++ b/src/duckstation-qt/interfacesettingswidget.cpp @@ -81,8 +81,25 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.createSaveStateBackups, "Main", "CreateSaveStateBackups", Settings::DEFAULT_SAVE_STATE_BACKUPS); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableDiscordPresence, "Main", "EnableDiscordPresence", false); + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.automaticallyResizeWindow, "Display", "AutoResizeWindow", + false); connect(m_ui.renderToSeparateWindow, &QCheckBox::checkStateChanged, this, - &InterfaceSettingsWidget::onRenderToSeparateWindowChanged); + &InterfaceSettingsWidget::updateRenderToSeparateWindowOptions); + connect(m_ui.hideMainWindow, &QCheckBox::checkStateChanged, this, + &InterfaceSettingsWidget::updateRenderToSeparateWindowOptions); + +#ifdef _WIN32 + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableWindowRoundedCorners, "Main", + "DisableWindowRoundedCorners", false); +#else + QtUtils::SafeDeleteWidget(m_ui.disableWindowRoundedCorners); +#endif +#ifdef __APPLE__ + SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useFractionalWindowScale, "Main", "UseFractionalWindowScale", + true); +#else + QtUtils::SafeDeleteWidget(m_ui.useFractionalWindowScale); +#endif if (!m_dialog->isPerGameSettings()) { @@ -110,12 +127,15 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget } else { - delete m_ui.appearanceGroup; - m_ui.appearanceGroup = nullptr; - m_ui.languageLabel = nullptr; - m_ui.language = nullptr; - m_ui.themeLabel = nullptr; - m_ui.theme = nullptr; + QtUtils::SafeDeleteWidget(m_ui.languageLabel); + QtUtils::SafeDeleteWidget(m_ui.language); + QtUtils::SafeDeleteWidget(m_ui.themeLabel); + QtUtils::SafeDeleteWidget(m_ui.theme); + + // On Linux, we don't have any rounded corner or fractional scaling options. +#if !defined(_WIN32) && !defined(__APPLE__) + QtUtils::SafeDeleteWidget(m_ui.appearanceGroup); +#endif delete m_ui.updatesGroup; m_ui.autoUpdateTagLabel = nullptr; @@ -127,7 +147,7 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget m_ui.checkForUpdates = nullptr; } - onRenderToSeparateWindowChanged(); + updateRenderToSeparateWindowOptions(); dialog->registerWidgetHelp(m_ui.confirmGameClose, tr("Confirm Game Close"), tr("Checked"), tr("Determines whether a prompt will be displayed to confirm closing the game.")); @@ -159,13 +179,27 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget m_ui.renderToSeparateWindow, tr("Render To Separate Window"), tr("Checked"), tr("Renders the display of the simulated console to the main window of the application, over " "the game list. If checked, the display will render in a separate window.")); + dialog->registerWidgetHelp(m_ui.hideMouseCursor, tr("Hide Cursor In Fullscreen"), tr("Checked"), + tr("Hides the mouse pointer/cursor when the emulator is in fullscreen mode.")); dialog->registerWidgetHelp( m_ui.hideMainWindow, tr("Hide Main Window When Running"), tr("Unchecked"), tr("Hides the main window of the application while the game is displayed in a separate window.")); dialog->registerWidgetHelp(m_ui.disableWindowResizing, tr("Disable Window Resizing"), tr("Unchecked"), tr("Prevents resizing of the window while a game is running.")); - dialog->registerWidgetHelp(m_ui.hideMouseCursor, tr("Hide Cursor In Fullscreen"), tr("Checked"), - tr("Hides the mouse pointer/cursor when the emulator is in fullscreen mode.")); + dialog->registerWidgetHelp(m_ui.automaticallyResizeWindow, tr("Automatically Resize Window"), tr("Unchecked"), + tr("Automatically resizes the window to match the internal resolution. For high " + "internal resolutions, this will create very large windows.")); + +#if defined(_WIN32) + dialog->registerWidgetHelp( + m_ui.disableWindowRoundedCorners, tr("Disable Window Rounded Corners"), tr("Unchecked"), + tr( + "Disables the rounding of windows automatically applied in Windows 11, which may obscure parts of the content.")); +#elif defined(__APPLE__) + dialog->registerWidgetHelp( + m_ui.useFractionalWindowScale, tr("Use Fractional Window Scale"), tr("Checked"), + tr("Calculates the true scaling factor for your display, avoiding the downsampling applied by MacOS.")); +#endif if (!m_dialog->isPerGameSettings()) { @@ -222,9 +256,10 @@ void InterfaceSettingsWidget::populateLanguageDropdown(QComboBox* cb) } } -void InterfaceSettingsWidget::onRenderToSeparateWindowChanged() +void InterfaceSettingsWidget::updateRenderToSeparateWindowOptions() { - m_ui.hideMainWindow->setEnabled(m_ui.renderToSeparateWindow->isChecked()); + const bool render_to_separate_window = m_dialog->getEffectiveBoolValue("Main", "RenderToSeparateWindow", false); + m_ui.hideMainWindow->setEnabled(render_to_separate_window); } void InterfaceSettingsWidget::onLanguageChanged() diff --git a/src/duckstation-qt/interfacesettingswidget.h b/src/duckstation-qt/interfacesettingswidget.h index 25f397e0b..ae423da86 100644 --- a/src/duckstation-qt/interfacesettingswidget.h +++ b/src/duckstation-qt/interfacesettingswidget.h @@ -23,9 +23,7 @@ Q_SIGNALS: void themeChanged(); private: - void setupAdditionalUi(); - - void onRenderToSeparateWindowChanged(); + void updateRenderToSeparateWindowOptions(); void onLanguageChanged(); Ui::InterfaceSettingsWidget m_ui; diff --git a/src/duckstation-qt/interfacesettingswidget.ui b/src/duckstation-qt/interfacesettingswidget.ui index e17960a76..70ffa0f58 100644 --- a/src/duckstation-qt/interfacesettingswidget.ui +++ b/src/duckstation-qt/interfacesettingswidget.ui @@ -116,23 +116,30 @@ + + + Hide Cursor In Fullscreen + + + + Hide Main Window When Running - - + + - Disable Window Resizing + Automatically Resize Window - - + + - Hide Cursor In Fullscreen + Disable Window Resizing @@ -165,6 +172,20 @@ + + + + Disable Window Rounded Corners + + + + + + + Use Fractional Window Scale + + + diff --git a/src/duckstation-qt/qtutils.h b/src/duckstation-qt/qtutils.h index eb8845d82..1b7bf7a37 100644 --- a/src/duckstation-qt/qtutils.h +++ b/src/duckstation-qt/qtutils.h @@ -73,6 +73,17 @@ inline void CloseAndDeleteWindow(T*& window) window = nullptr; } +/// Safely deletes a widget and nulls the reference. +template +inline void SafeDeleteWidget(T*& widget) +{ + if (!widget) + return; + + delete widget; + widget = nullptr; +} + /// For any positive values, sets the corresponding column width to the specified value. /// Any values of 0 will set the column's width based on the content. /// Any values of -1 will stretch the column to use the remaining space. diff --git a/src/duckstation-qt/resources/duckstation-qt.qrc b/src/duckstation-qt/resources/duckstation-qt.qrc index 1b4c1533c..9ed962ace 100644 --- a/src/duckstation-qt/resources/duckstation-qt.qrc +++ b/src/duckstation-qt/resources/duckstation-qt.qrc @@ -20,6 +20,7 @@ icons/black/svg/arrow-up-line.svg icons/black/svg/artboard-2-line.svg icons/black/svg/camera-switch-line.svg + icons/black/svg/chat-history-line.svg icons/black/svg/chat-off-line.svg icons/black/svg/cheats-line.svg icons/black/svg/checkbox-multiple-blank-line.svg @@ -171,6 +172,7 @@ icons/white/svg/arrow-up-line.svg icons/white/svg/artboard-2-line.svg icons/white/svg/camera-switch-line.svg + icons/white/svg/chat-history-line.svg icons/white/svg/chat-off-line.svg icons/white/svg/cheats-line.svg icons/white/svg/checkbox-checked-disabled.svg diff --git a/src/duckstation-qt/resources/icons/black/svg/chat-history-line.svg b/src/duckstation-qt/resources/icons/black/svg/chat-history-line.svg new file mode 100644 index 000000000..4791cd663 --- /dev/null +++ b/src/duckstation-qt/resources/icons/black/svg/chat-history-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/duckstation-qt/resources/icons/white/svg/chat-history-line.svg b/src/duckstation-qt/resources/icons/white/svg/chat-history-line.svg new file mode 100644 index 000000000..586ec2055 --- /dev/null +++ b/src/duckstation-qt/resources/icons/white/svg/chat-history-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/duckstation-qt/settingswindow.h b/src/duckstation-qt/settingswindow.h index 2239a2a93..d0c584cd5 100644 --- a/src/duckstation-qt/settingswindow.h +++ b/src/duckstation-qt/settingswindow.h @@ -86,7 +86,7 @@ public: bool getEffectiveBoolValue(const char* section, const char* key, bool default_value) const; int getEffectiveIntValue(const char* section, const char* key, int default_value) const; float getEffectiveFloatValue(const char* section, const char* key, float default_value) const; - std::string getEffectiveStringValue(const char* section, const char* key, const char* default_value) const; + std::string getEffectiveStringValue(const char* section, const char* key, const char* default_value = "") const; Qt::CheckState getCheckState(const char* section, const char* key, bool default_value); // Helper functions for reading setting values for this layer (game settings or global).