Merge pull request #14062 from Simonx22/macos-design-fixes

macOS: UI fixes for dark mode
This commit is contained in:
OatmealDome 2025-11-06 20:20:05 -05:00 committed by GitHub
commit 852b7d85b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 100 additions and 30 deletions

View File

@ -3,9 +3,13 @@
#include "DolphinQt/Config/SettingsWindow.h"
#include <QApplication>
#include <QColor>
#include <QDialogButtonBox>
#include <QEvent>
#include <QHBoxLayout>
#include <QListWidget>
#include <QPalette>
#include <QStackedWidget>
#include <QTabWidget>
#include <QVBoxLayout>
@ -17,6 +21,7 @@
#include "DolphinQt/MainWindow.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/AdvancedPane.h"
#include "DolphinQt/Settings/AudioPane.h"
#include "DolphinQt/Settings/GameCubePane.h"
@ -34,7 +39,7 @@ StackedSettingsWindow::StackedSettingsWindow(QWidget* parent) : QDialog{parent}
auto* const layout = new QHBoxLayout{this};
// Calculated value for the padding in our list items.
const int list_item_padding = layout->contentsMargins().left() / 2;
m_list_item_padding = layout->contentsMargins().left() / 2;
// Eliminate padding around layouts.
layout->setContentsMargins(QMargins{});
@ -46,33 +51,7 @@ StackedSettingsWindow::StackedSettingsWindow(QWidget* parent) : QDialog{parent}
m_navigation_list->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
m_navigation_list->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
// FYI: "base" is the window color on Windows and "alternate-base" is very high contrast on macOS.
const auto* const list_background =
#if !defined(__APPLE__)
"palette(alternate-base)";
#else
"palette(base)";
#endif
m_navigation_list->setStyleSheet(
QString::fromUtf8(
// Remove border around entire widget and adjust background color.
"QListWidget { border: 0; background: %1; } "
// Note: padding-left is broken unless border is set, which then breaks colors.
// see: https://bugreports.qt.io/browse/QTBUG-122698
"QListWidget::item { padding-top: %2px; padding-bottom: %2px; } "
// Maintain selected item color when unfocused.
"QListWidget::item:selected { background: palette(highlight); "
#if !defined(__APPLE__)
// Prevent text color change on focus loss.
// This seems to breaks the nice white text on macOS.
"color: palette(highlighted-text); "
#endif
"} "
// Remove ugly dotted outline on selected row (Windows and GNOME).
"* { outline: none; } ")
.arg(QString::fromUtf8(list_background))
.arg(list_item_padding));
UpdateNavigationListStyle();
layout->addWidget(m_navigation_list);
@ -104,6 +83,90 @@ void StackedSettingsWindow::OnDoneCreatingPanes()
QtUtils::AdjustSizeWithinScreen(this);
}
void StackedSettingsWindow::changeEvent(QEvent* event)
{
QDialog::changeEvent(event);
const auto type = event->type();
const bool palette_changed = type == QEvent::PaletteChange;
const bool application_palette_changed = type == QEvent::ApplicationPaletteChange;
const bool style_changed = type == QEvent::StyleChange;
const bool theme_event = type == QEvent::ThemeChange;
const bool theme_changed = application_palette_changed || theme_event;
if (theme_changed && !m_handling_theme_change)
{
m_handling_theme_change = true;
Settings::Instance().ApplyStyle();
// Ensure the dialog and its children adopt the new system palette.
setPalette(qApp->palette());
Settings::Instance().TriggerThemeChanged();
m_handling_theme_change = false;
}
if (palette_changed || application_palette_changed || style_changed || theme_event)
UpdateNavigationListStyle();
}
void StackedSettingsWindow::UpdateNavigationListStyle()
{
if (!m_navigation_list)
return;
// FYI: "base" is the window color on Windows and "alternate-base" is very high contrast on macOS.
const auto* const list_background =
#if !defined(__APPLE__)
"palette(alternate-base)";
#else
"palette(base)";
#endif
m_navigation_list->setStyleSheet(
QString::fromUtf8(
// Remove border around entire widget and adjust background color.
"QListWidget { border: 0; background: %1; } "
// Note: padding-left is broken unless border is set, which then breaks colors.
// see: https://bugreports.qt.io/browse/QTBUG-122698
"QListWidget::item { padding-top: %2px; padding-bottom: %2px; } "
// Maintain selected item color when unfocused.
"QListWidget::item:selected { background: palette(highlight); "
// Prevent text color change on focus loss.
"color: palette(highlighted-text); "
"} "
// Remove ugly dotted outline on selected row (Windows and GNOME).
"* { outline: none; } ")
.arg(QString::fromUtf8(list_background))
.arg(m_list_item_padding));
QPalette list_palette = m_navigation_list->palette();
const QPalette app_palette = qApp->palette();
QColor highlight_color = app_palette.color(QPalette::Active, QPalette::Highlight);
QColor highlighted_text = app_palette.color(QPalette::Active, QPalette::HighlightedText);
#if defined(__APPLE__)
const bool is_dark_theme = Settings::Instance().IsThemeDark();
// The default macOS accent is quite light in our list; darken it for readability in light mode.
if (!is_dark_theme)
{
highlight_color = highlight_color.darker(130);
highlighted_text = QColor(Qt::white);
}
#endif
for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive})
{
list_palette.setColor(group, QPalette::Base, app_palette.color(group, QPalette::Base));
list_palette.setColor(group, QPalette::AlternateBase,
app_palette.color(group, QPalette::AlternateBase));
list_palette.setColor(group, QPalette::Highlight, highlight_color);
list_palette.setColor(group, QPalette::HighlightedText, highlighted_text);
}
m_navigation_list->setPalette(list_palette);
}
void StackedSettingsWindow::AddPane(QWidget* widget, const QString& name)
{
m_stacked_panes->addWidget(widget);

View File

@ -8,6 +8,7 @@
class QStackedWidget;
class QListWidget;
class MainWindow;
class QEvent;
// A settings window with a QListWidget to switch between panes of a QStackedWidget.
class StackedSettingsWindow : public QDialog
@ -27,9 +28,15 @@ protected:
// For derived classes to call after they create their settings panes.
void OnDoneCreatingPanes();
void changeEvent(QEvent* event) override;
private:
QStackedWidget* m_stacked_panes;
QListWidget* m_navigation_list;
void UpdateNavigationListStyle();
QStackedWidget* m_stacked_panes = nullptr;
QListWidget* m_navigation_list = nullptr;
int m_list_item_padding = 0;
bool m_handling_theme_change = false;
};
enum class SettingsWindowPaneIndex : int