From 1765590a6fa106710c4ff12ffce56201570341fe Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 5 Jan 2025 16:39:57 +1000 Subject: [PATCH] Qt: Add 'Disable Window Rounded Corners' option --- src/duckstation-qt/advancedsettingswidget.cpp | 7 +++- src/duckstation-qt/mainwindow.cpp | 26 +++++++++++++ src/util/platform_misc.h | 11 ++++++ src/util/platform_misc_mac.mm | 6 +++ src/util/platform_misc_unix.cpp | 6 +++ src/util/platform_misc_win32.cpp | 37 +++++++++++++------ 6 files changed, 81 insertions(+), 12 deletions(-) diff --git a/src/duckstation-qt/advancedsettingswidget.cpp b/src/duckstation-qt/advancedsettingswidget.cpp index 6a0b1f845..4af15ca9c 100644 --- a/src/duckstation-qt/advancedsettingswidget.cpp +++ b/src/duckstation-qt/advancedsettingswidget.cpp @@ -238,6 +238,9 @@ void AdvancedSettingsWidget::addTweakOptions() static_cast(SaveStateCompressionMode::Count), Settings::DEFAULT_SAVE_STATE_COMPRESSION_MODE); + addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Disable Window Rounded Corners"), "Main", + "DisableWindowRoundedCorners", false); + if (m_dialog->isPerGameSettings()) { addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display Active Start Offset"), "Display", @@ -295,10 +298,11 @@ void AdvancedSettingsWidget::onResetToDefaultClicked() int i = 0; setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply Game Settings - setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply compatibility settings + setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply Compatibility settings 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 + setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Disable Window Rounded Corners setIntRangeTweakOption(m_ui.tweakOptionTable, i++, static_cast(Settings::DEFAULT_DMA_MAX_SLICE_TICKS)); // DMA max slice ticks setIntRangeTweakOption(m_ui.tweakOptionTable, i++, @@ -331,6 +335,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked() sif->DeleteValue("Main", "ApplyCompatibilitySettings"); sif->DeleteValue("Main", "LoadDevicesFromSaveStates"); sif->DeleteValue("Main", "CompressSaveStates"); + sif->DeleteValue("Main", "DisableWindowRoundedCorners"); sif->DeleteValue("Display", "ActiveStartOffset"); sif->DeleteValue("Display", "ActiveEndOffset"); sif->DeleteValue("Display", "LineStartOffset"); diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index 66af60a0a..b79281c7b 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -32,6 +32,7 @@ #include "util/cd_image.h" #include "util/gpu_device.h" +#include "util/platform_misc.h" #include "common/assert.h" #include "common/error.h" @@ -83,6 +84,7 @@ static bool s_use_central_widget = false; #endif // UI thread VM validity. +static bool s_disable_window_rounded_corners = false; static bool s_system_valid = false; static bool s_system_paused = false; static bool s_fullscreen_ui_started = false; @@ -353,6 +355,9 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool else restoreDisplayWindowGeometryFromConfig(); container->showNormal(); + + if (s_disable_window_rounded_corners) + PlatformMisc::SetWindowRoundedCornerState(reinterpret_cast(container->winId()), false); } else if (s_use_central_widget) { @@ -1678,6 +1683,10 @@ void MainWindow::setupAdditionalUi() m_shortcuts.game_grid_zoom_out = new QShortcut(Qt::ControlModifier | Qt::Key_Minus, this, this, &MainWindow::onViewGameGridZoomOutActionTriggered); + s_disable_window_rounded_corners = Host::GetBaseBoolSettingValue("Main", "DisableWindowRoundedCorners", false); + if (s_disable_window_rounded_corners) + PlatformMisc::SetWindowRoundedCornerState(reinterpret_cast(winId()), false); + #ifdef ENABLE_RAINTEGRATION if (Achievements::IsUsingRAIntegration()) { @@ -2549,6 +2558,20 @@ void MainWindow::requestExit(bool allow_confirm /* = true */) void MainWindow::checkForSettingChanges() { + if (const bool disable_window_rounded_corners = + Host::GetBaseBoolSettingValue("Main", "DisableWindowRoundedCorners", false); + disable_window_rounded_corners != s_disable_window_rounded_corners) + { + s_disable_window_rounded_corners = disable_window_rounded_corners; + PlatformMisc::SetWindowRoundedCornerState(reinterpret_cast(winId()), !s_disable_window_rounded_corners); + + if (QWidget* container = getDisplayContainer(); container && !container->parent() && !container->isFullScreen()) + { + PlatformMisc::SetWindowRoundedCornerState(reinterpret_cast(container->winId()), + !s_disable_window_rounded_corners); + } + } + LogWindow::updateSettings(); updateWindowState(); } @@ -2647,6 +2670,9 @@ bool MainWindow::onCreateAuxiliaryRenderWindow(RenderAPI render_api, qint32 x, q if (!widget) return false; + if (s_disable_window_rounded_corners) + PlatformMisc::SetWindowRoundedCornerState(reinterpret_cast(widget->winId()), false); + const std::optional owi = QtUtils::GetWindowInfoForWidget(widget, render_api, error); if (!owi.has_value()) { diff --git a/src/util/platform_misc.h b/src/util/platform_misc.h index b874d64d0..20098f9c7 100644 --- a/src/util/platform_misc.h +++ b/src/util/platform_misc.h @@ -8,22 +8,33 @@ class Error; namespace PlatformMisc { + bool InitializeSocketSupport(Error* error); + void SuspendScreensaver(); void ResumeScreensaver(); /// Abstracts platform-specific code for asynchronously playing a sound. /// On Windows, this will use PlaySound(). On Linux, it will shell out to aplay. On MacOS, it uses NSSound. bool PlaySoundAsync(const char* path); + +/// Sets the rounded corner state for a window. +/// Currently only supported on Windows. +bool SetWindowRoundedCornerState(void* window_handle, bool enabled, Error* error = nullptr); + } // namespace PlatformMisc namespace Host { + /// Return the current window handle. Needed for DInput. std::optional GetTopLevelWindowInfo(); + } // namespace Host // TODO: Move all the other Cocoa stuff in here. namespace CocoaTools { + /// Returns the refresh rate of the display the window is placed on. std::optional GetViewRefreshRate(const WindowInfo& wi, Error* error); + } // namespace CocoaTools diff --git a/src/util/platform_misc_mac.mm b/src/util/platform_misc_mac.mm index a0077aa21..507398eff 100644 --- a/src/util/platform_misc_mac.mm +++ b/src/util/platform_misc_mac.mm @@ -88,6 +88,12 @@ bool PlatformMisc::PlaySoundAsync(const char* path) return result; } +bool PlatformMisc::SetWindowRoundedCornerState(void* window_handle, bool enabled, Error* error /* = nullptr */) +{ + Error::SetStringView(error, "Unsupported on this platform."); + return false; +} + void* CocoaTools::CreateMetalLayer(const WindowInfo& wi, Error* error) { // Punt off to main thread if we're not calling from it already. diff --git a/src/util/platform_misc_unix.cpp b/src/util/platform_misc_unix.cpp index 995193fb5..f03db1d1b 100644 --- a/src/util/platform_misc_unix.cpp +++ b/src/util/platform_misc_unix.cpp @@ -234,3 +234,9 @@ bool PlatformMisc::PlaySoundAsync(const char* path) return false; #endif } + +bool PlatformMisc::SetWindowRoundedCornerState(void* window_handle, bool enabled, Error* error /* = nullptr */) +{ + Error::SetStringView(error, "Unsupported on this platform."); + return false; +} diff --git a/src/util/platform_misc_win32.cpp b/src/util/platform_misc_win32.cpp index a7daa5ae8..041bf980a 100644 --- a/src/util/platform_misc_win32.cpp +++ b/src/util/platform_misc_win32.cpp @@ -16,6 +16,7 @@ #include "common/windows_headers.h" #include #include +#include #include LOG_CHANNEL(PlatformMisc); @@ -26,18 +27,21 @@ static std::once_flag s_winsock_initializer; bool PlatformMisc::InitializeSocketSupport(Error* error) { - std::call_once(s_winsock_initializer, [](Error* error) { - WSADATA wsa = {}; - if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) - { - Error::SetSocket(error, "WSAStartup() failed: ", WSAGetLastError()); - return false; - } + std::call_once( + s_winsock_initializer, + [](Error* error) { + WSADATA wsa = {}; + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + { + Error::SetSocket(error, "WSAStartup() failed: ", WSAGetLastError()); + return false; + } - s_winsock_initialized = true; - std::atexit([]() { WSACleanup(); }); - return true; - }, error); + s_winsock_initialized = true; + std::atexit([]() { WSACleanup(); }); + return true; + }, + error); return s_winsock_initialized; } @@ -83,3 +87,14 @@ bool PlatformMisc::PlaySoundAsync(const char* path) const std::wstring wpath(FileSystem::GetWin32Path(path)); return PlaySoundW(wpath.c_str(), NULL, SND_ASYNC | SND_NODEFAULT); } + +bool PlatformMisc::SetWindowRoundedCornerState(void* window_handle, bool enabled, Error* error) +{ + const DWM_WINDOW_CORNER_PREFERENCE value = enabled ? DWMWCP_DEFAULT : DWMWCP_DONOTROUND; + const HRESULT hr = + DwmSetWindowAttribute(static_cast(window_handle), DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value)); + if (FAILED(hr)) + Error::SetHResult(error, "DwmSetWindowAttribute(DWMWA_WINDOW_CORNER_PREFERENCE) failed: ", hr); + + return SUCCEEDED(hr); +}