Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert dark mode regressions on Windows 10 #7463

Merged
merged 11 commits into from
Nov 19, 2024
Merged
23 changes: 5 additions & 18 deletions src/gui/application.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/gui/application.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/application.cpp

File src/gui/application.cpp does not conform to Custom style guidelines. (lines 369)
* Copyright (C) by Duncan Mac-Vicar P. <[email protected]>
* Copyright (C) by Klaas Freitag <[email protected]>
* Copyright (C) by Daniel Molkentin <[email protected]>
Expand Down Expand Up @@ -126,21 +126,6 @@

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

#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 @@
// 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 @@

_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 @@
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 @@ -15,7 +15,7 @@
#ifndef APPLICATION_H
#define APPLICATION_H

#include <QApplication>

Check failure on line 18 in src/gui/application.h

View workflow job for this annotation

GitHub Actions / build

src/gui/application.h:18:10 [clang-diagnostic-error]

'QApplication' file not found
#include <QPointer>
#include <QQueue>
#include <QTimer>
Expand Down Expand Up @@ -96,6 +96,7 @@
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 @@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <QtGlobal>

Check failure on line 15 in src/gui/main.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/main.cpp:15:10 [clang-diagnostic-error]

'QtGlobal' file not found

#include <cmath>
#include <csignal>
Expand All @@ -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 @@
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
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/libsync/theme.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/libsync/theme.cpp

File src/libsync/theme.cpp does not conform to Custom style guidelines. (lines 71, 401, 972, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1018, 1033, 1034)
* Copyright (C) by Klaas Freitag <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
Expand Down 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 @@
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)

Check warning on line 80 in src/libsync/theme.cpp

View workflow job for this annotation

GitHub Actions / build

src/libsync/theme.cpp:80:1 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'Q_LOGGING_CATEGORY' is non-const and globally accessible, consider making it const

Theme *Theme::_instance = nullptr;

Theme *Theme::instance()
Expand Down Expand Up @@ -354,30 +367,40 @@
#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 @@ -946,27 +969,74 @@
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 @@ -1010,4 +1080,14 @@
}
}

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 @@ -15,7 +15,7 @@
#ifndef _THEME_H
#define _THEME_H

#include <QIcon>

Check failure on line 18 in src/libsync/theme.h

View workflow job for this annotation

GitHub Actions / build

src/libsync/theme.h:18:10 [clang-diagnostic-error]

'QIcon' file not found
#include <QObject>
#include <QPalette>
#include <QGuiApplication>
Expand Down Expand Up @@ -67,6 +67,7 @@

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 @@

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 @@

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
Loading