Skip to content

Commit

Permalink
Merge pull request #7516 from nextcloud/backport/7463/stable-3.14
Browse files Browse the repository at this point in the history
[stable-3.14] Revert dark mode regressions on Windows 10
  • Loading branch information
mgallien authored Nov 19, 2024
2 parents 0fc7fcc + f975e97 commit 1026e6e
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 50 deletions.
23 changes: 5 additions & 18 deletions src/gui/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,6 @@ namespace {

// ----------------------------------------------------------------------------------

#ifdef Q_OS_WIN
class WindowsNativeEventFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override {
const auto msg = static_cast<MSG *>(message);
if(msg->message == WM_SYSCOLORCHANGE || msg->message == WM_SETTINGCHANGE) {
if (const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance())) {
emit ptr->paletteChanged(ptr->palette());
}
}
return false;
}
};
#endif

bool Application::configVersionMigration()
{
QStringList deleteKeys, ignoreKeys;
Expand Down Expand Up @@ -237,9 +222,6 @@ Application::Application(int &argc, char **argv)
// Ensure OpenSSL config file is only loaded from app directory
QString opensslConf = QCoreApplication::applicationDirPath() + QString("/openssl.cnf");
qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());

// Set up event listener for Windows theme changing
installNativeEventFilter(new WindowsNativeEventFilter());
#endif

// TODO: Can't set this without breaking current config paths
Expand Down Expand Up @@ -384,6 +366,8 @@ Application::Application(int &argc, char **argv)

_theme->setSystrayUseMonoIcons(ConfigFile().monoIcons());
connect(_theme, &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
connect(this, &Application::systemPaletteChanged,
_theme, &Theme::systemPaletteHasChanged);

#if defined(Q_OS_WIN)
_shellExtensionsServer.reset(new ShellExtensionsServer);
Expand Down Expand Up @@ -1127,6 +1111,9 @@ bool Application::event(QEvent *event)
qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;
showHint(errorParsingLocalFileEditingUrl.toStdString());
}
} else if (event->type() == QEvent::ApplicationPaletteChange) {
qCInfo(lcApplication) << "application palette changed";
emit systemPaletteChanged();
}
return SharedTools::QtSingleApplication::event(event);
}
Expand Down
1 change: 1 addition & 0 deletions src/gui/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public slots:
void folderRemoved();
void folderStateChanged(OCC::Folder *);
void isShowingSettingsDialog();
void systemPaletteChanged();

protected slots:
void slotParseMessage(const QString &, QObject *);
Expand Down
9 changes: 9 additions & 0 deletions src/gui/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@
#include <QMessageBox>
#include <QDebug>
#include <QQuickStyle>
#include <QStyle>
#include <QStyleFactory>
#include <QQuickWindow>
#include <QSurfaceFormat>
#include <QOperatingSystemVersion>

using namespace OCC;

Expand Down Expand Up @@ -82,6 +85,12 @@ int main(int argc, char **argv)
QQuickStyle::setStyle(style);
QQuickStyle::setFallbackStyle(QStringLiteral("Fusion"));

#if defined Q_OS_WIN
if (QOperatingSystemVersion::current().version() < QOperatingSystemVersion::Windows11.version()) {
QApplication::setStyle(QStyleFactory::create("Fusion"));
}
#endif

OCC::Application app(argc, argv);

#ifndef Q_OS_WIN
Expand Down
5 changes: 4 additions & 1 deletion src/gui/networksettings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
Expand Down
128 changes: 104 additions & 24 deletions src/libsync/theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
#include <QPainter>
#include <QJsonDocument>
#include <QJsonArray>
#include <QLoggingCategory>

#ifdef Q_OS_WIN
#include <windows.h>
#endif

#include "nextcloudtheme.h"

Expand Down Expand Up @@ -62,10 +67,18 @@ bool shouldPreferSvg()
return QByteArray(APPLICATION_ICON_SET).toUpper() == QByteArrayLiteral("SVG");
}

#ifdef Q_OS_WIN
bool isWindows11OrGreater() {
return QOperatingSystemVersion::current().version() >= QOperatingSystemVersion::Windows11.version();
}
#endif

}

namespace OCC {

Q_LOGGING_CATEGORY(lcTheme, "nextcloud.gui.theme", QtInfoMsg)

Theme *Theme::_instance = nullptr;

Theme *Theme::instance()
Expand Down Expand Up @@ -354,30 +367,40 @@ Theme::Theme()
#if defined(Q_OS_WIN)
// Windows does not provide a dark theme for Win32 apps so let's come up with a palette
// Credit to https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle
reserveDarkPalette = qApp->palette();

reserveDarkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
reserveDarkPalette.setColor(QPalette::WindowText, Qt::white);
reserveDarkPalette.setColor(QPalette::Disabled, QPalette::WindowText,
QColor(127, 127, 127));
reserveDarkPalette.setColor(QPalette::Button, QColor(127, 127, 127));
reserveDarkPalette.setColor(QPalette::Light, QColor(20, 20, 20));
reserveDarkPalette.setColor(QPalette::Midlight, QColor(78, 78, 78));
reserveDarkPalette.setColor(QPalette::Dark, QColor(191, 191, 191));
reserveDarkPalette.setColor(QPalette::Mid, QColor(95, 95, 95));
reserveDarkPalette.setColor(QPalette::Text, Qt::white);
reserveDarkPalette.setColor(QPalette::BrightText, Qt::red);
reserveDarkPalette.setColor(QPalette::ButtonText, Qt::white);
reserveDarkPalette.setColor(QPalette::Base, QColor(42, 42, 42));
reserveDarkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
reserveDarkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
reserveDarkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
reserveDarkPalette.setColor(QPalette::HighlightedText, Qt::white);
reserveDarkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
reserveDarkPalette.setColor(QPalette::LinkVisited, QColor(42, 130, 218));
reserveDarkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
reserveDarkPalette.setColor(QPalette::NoRole, QColor(127, 127, 127));
reserveDarkPalette.setColor(QPalette::ToolTipBase, Qt::white);
reserveDarkPalette.setColor(QPalette::ToolTipText, QColor(53, 53, 53));
reserveDarkPalette.setColor(QPalette::Text, Qt::white);
reserveDarkPalette.setColor(QPalette::PlaceholderText, QColor(44, 44, 44));
reserveDarkPalette.setColor(QPalette::Accent, QColor(127, 127, 200));

reserveDarkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
reserveDarkPalette.setColor(QPalette::Dark, QColor(35, 35, 35));
reserveDarkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
reserveDarkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
reserveDarkPalette.setColor(QPalette::ButtonText, Qt::white);
reserveDarkPalette.setColor(QPalette::Disabled, QPalette::ButtonText,
QColor(127, 127, 127));
reserveDarkPalette.setColor(QPalette::BrightText, Qt::red);
reserveDarkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
reserveDarkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
reserveDarkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
reserveDarkPalette.setColor(QPalette::HighlightedText, Qt::white);
reserveDarkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText,
QColor(127, 127, 127));
reserveDarkPalette.setColor(QPalette::Disabled, QPalette::WindowText,
QColor(127, 127, 127));
connectToPaletteSignal();
#endif

#ifdef APPLICATION_SERVER_URL_ENFORCE
Expand Down Expand Up @@ -942,27 +965,74 @@ QColor Theme::defaultColor()
void Theme::connectToPaletteSignal()
{
if (!_paletteSignalsConnected) {
if (const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance())) {
if (const auto ptr = qobject_cast<QGuiApplication*>(qApp)) {
connect(ptr->styleHints(), &QStyleHints::colorSchemeChanged, this, &Theme::darkModeChanged);
_paletteSignalsConnected = true;
}
}
}

bool Theme::darkMode()
QVariantMap Theme::systemPalette() const
{
connectToPaletteSignal();
switch (qGuiApp->styleHints()->colorScheme())
{
case Qt::ColorScheme::Dark:
return true;
case Qt::ColorScheme::Light:
return false;
case Qt::ColorScheme::Unknown:
return Theme::isDarkColor(QGuiApplication::palette().window().color());
auto systemPalette = QGuiApplication::palette();
#if defined(Q_OS_WIN)
if (darkMode() && !isWindows11OrGreater()) {
systemPalette = reserveDarkPalette;
qApp->setPalette(reserveDarkPalette);
}
#else

return false;
#endif

return QVariantMap {
{ QStringLiteral("base"), systemPalette.base().color() },
{ QStringLiteral("alternateBase"), systemPalette.alternateBase().color() },
{ QStringLiteral("text"), systemPalette.text().color() },
{ QStringLiteral("toolTipBase"), systemPalette.toolTipBase().color() },
{ QStringLiteral("toolTipText"), systemPalette.toolTipText().color() },
{ QStringLiteral("brightText"), systemPalette.brightText().color() },
{ QStringLiteral("buttonText"), systemPalette.buttonText().color() },
{ QStringLiteral("button"), systemPalette.button().color() },
{ QStringLiteral("highlightedText"), systemPalette.highlightedText().color() },
{ QStringLiteral("placeholderText"), systemPalette.placeholderText().color() },
{ QStringLiteral("windowText"), systemPalette.windowText().color() },
{ QStringLiteral("window"), systemPalette.window().color() },
{ QStringLiteral("dark"), systemPalette.dark().color() },
{ QStringLiteral("highlight"), systemPalette.highlight().color() },
{ QStringLiteral("light"), systemPalette.light().color() },
{ QStringLiteral("link"), systemPalette.link().color() },
{ QStringLiteral("midlight"), systemPalette.midlight().color() },
{ QStringLiteral("mid"), systemPalette.mid().color() },
{ QStringLiteral("linkVisited"), systemPalette.linkVisited().color() },
{ QStringLiteral("shadow"), systemPalette.shadow().color() },
};
}

bool Theme::darkMode() const
{
const auto isDarkFromStyle = [] {
switch (qGuiApp->styleHints()->colorScheme())
{
case Qt::ColorScheme::Dark:
return true;
case Qt::ColorScheme::Light:
return false;
case Qt::ColorScheme::Unknown:
return Theme::isDarkColor(QGuiApplication::palette().window().color());
}

return false;
};

#ifdef Q_OS_WIN
static const auto darkModeSubkey = QStringLiteral("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize");
if (!isWindows11OrGreater() &&
Utility::registryKeyExists(HKEY_CURRENT_USER, darkModeSubkey) &&
!Utility::registryGetKeyValue(HKEY_CURRENT_USER, darkModeSubkey, QStringLiteral("AppsUseLightTheme")).toBool()) {
return true;
}
#endif
return isDarkFromStyle();
}

void Theme::setOverrideServerUrl(const QString &overrideServerUrl)
Expand Down Expand Up @@ -997,4 +1067,14 @@ void Theme::setStartLoginFlowAutomatically(bool startLoginFlowAuto)
}
}

void Theme::systemPaletteHasChanged()
{
qCInfo(lcTheme()) << "system palette changed";
#ifdef Q_OS_WIN
if (darkMode() && !isWindows11OrGreater()) {
qApp->setPalette(reserveDarkPalette);
}
#endif
}

} // end namespace client
6 changes: 5 additions & 1 deletion src/libsync/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject

Q_PROPERTY(QColor defaultColor READ defaultColor CONSTANT)

Q_PROPERTY(QVariantMap systemPalette READ systemPalette NOTIFY systemPaletteChanged)
Q_PROPERTY(bool darkMode READ darkMode NOTIFY darkModeChanged)
public:
enum CustomMediaType {
Expand Down Expand Up @@ -600,13 +601,15 @@ class OWNCLOUDSYNC_EXPORT Theme : public QObject

static constexpr const char *themePrefix = ":/client/theme/";

bool darkMode();
[[nodiscard]] QVariantMap systemPalette() const;
[[nodiscard]] bool darkMode() const;

public slots:
void setOverrideServerUrl(const QString &overrideServerUrl);
void setForceOverrideServerUrl(bool forceOverride);
void setVfsEnabled(bool enabled);
void setStartLoginFlowAutomatically(bool startLoginFlowAuto);
void systemPaletteHasChanged();

protected:
#ifndef TOKEN_AUTH_ONLY
Expand All @@ -624,6 +627,7 @@ public slots:

signals:
void systrayUseMonoIconsChanged(bool);
void systemPaletteChanged(const QPalette &palette);
void darkModeChanged();
void overrideServerUrlChanged();
void forceOverrideServerUrlChanged();
Expand Down
9 changes: 3 additions & 6 deletions theme/Style/Style.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,17 @@ QtObject {
readonly property int pixelSize: fontMetrics.font.pixelSize
readonly property bool darkMode: Theme.darkMode

property SystemPalette nativePalette: SystemPalette {
}

// Colors
readonly property color ncBlue: Theme.wizardHeaderBackgroundColor
readonly property color ncHeaderTextColor: Theme.wizardHeaderTitleColor
readonly property color ncTextColor: nativePalette.text
readonly property color ncTextColor: Theme.systemPalette.windowText
readonly property color ncTextBrightColor: "white"
readonly property color ncSecondaryTextColor: "#808080"
readonly property color lightHover: Theme.darkMode ? Qt.lighter(backgroundColor, 2) : Qt.darker(backgroundColor, 1.05)
readonly property color darkerHover: Theme.darkMode ? Qt.lighter(backgroundColor, 2.35) : Qt.darker(backgroundColor, 1.25)
readonly property color menuBorder: Theme.darkMode ? Qt.lighter(backgroundColor, 2.5) : Qt.darker(backgroundColor, 1.5)
readonly property color backgroundColor: nativePalette.window
readonly property color buttonBackgroundColor: nativePalette.button
readonly property color backgroundColor: Theme.systemPalette.window
readonly property color buttonBackgroundColor: Theme.systemPalette.button
readonly property color positiveColor: Qt.rgba(0.38, 0.74, 0.38, 1)

readonly property color currentUserHeaderColor: UserModel.currentUser ? UserModel.currentUser.headerColor : ncBlue
Expand Down

0 comments on commit 1026e6e

Please sign in to comment.