Skip to content

Commit 48cea89

Browse files
committed
feat: sync dock fonts and improve launcher matching
Sync the dock font assets with the new UI behavior. Improve launcher matching so fashion mode items resolve correctly.
1 parent 4e28f2e commit 48cea89

19 files changed

Lines changed: 829 additions & 106 deletions

LICENSES/OFL-1.1.txt

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
SIL OPEN FONT LICENSE
2+
3+
Version 1.1 - 26 February 2007
4+
5+
PREAMBLE
6+
7+
The goals of the Open Font License (OFL) are to stimulate worldwide
8+
development of collaborative font projects, to support the font creation
9+
efforts of academic and linguistic communities, and to provide a free and
10+
open framework in which fonts may be shared and improved in partnership
11+
with others.
12+
13+
The OFL allows the licensed fonts to be used, studied, modified and
14+
redistributed freely as long as they are not sold by themselves. The
15+
fonts, including any derivative works, can be bundled, embedded,
16+
redistributed and/or sold with any software provided that any reserved
17+
names are not used by derivative works. The fonts and derivatives,
18+
however, cannot be released under any other type of license. The
19+
requirement for fonts to remain under this license does not apply to any
20+
document created using the fonts or their derivatives.
21+
22+
DEFINITIONS
23+
24+
"Font Software" refers to the set of files released by the Copyright
25+
Holder(s) under this license and clearly marked as such. This may
26+
include source files, build scripts and documentation.
27+
28+
"Reserved Font Name" refers to any names specified as such after the
29+
copyright statement(s).
30+
31+
"Original Version" refers to the collection of Font Software components as
32+
distributed by the Copyright Holder(s).
33+
34+
"Modified Version" refers to any derivative made by adding to, deleting,
35+
or substituting -- in part or in whole -- any of the components of the
36+
Original Version, by changing formats or by porting the Font Software to a
37+
new environment.
38+
39+
"Author" refers to any designer, engineer, programmer, technical
40+
writer or other person who contributed to the Font Software.
41+
42+
PERMISSION & CONDITIONS
43+
44+
Permission is hereby granted, free of charge, to any person obtaining a
45+
copy of the Font Software, to use, study, copy, merge, embed, modify,
46+
redistribute, and sell modified and unmodified copies of the Font
47+
Software, subject to the following conditions:
48+
49+
1) Neither the Font Software nor any of its individual components, in
50+
Original or Modified Versions, may be sold by itself.
51+
52+
2) Original or Modified Versions of the Font Software may be bundled,
53+
redistributed and/or sold with any software, provided that each copy
54+
contains the above copyright notice and this license. These can be
55+
included either as stand-alone text files, human-readable headers or in
56+
the appropriate machine-readable metadata fields within text or binary
57+
files as long as those fields can be easily viewed by the user.
58+
59+
3) No Modified Version of the Font Software may use the Reserved Font
60+
Name(s) unless explicit written permission is granted by the corresponding
61+
Copyright Holder. This restriction only applies to the primary font name
62+
as presented to the users.
63+
64+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
65+
Software shall not be used to promote, endorse or advertise any Modified
66+
Version, except to acknowledge the contribution(s) of the Copyright
67+
Holder(s) and the Author(s) or with their explicit written permission.
68+
69+
5) The Font Software, modified or unmodified, in part or in whole, must
70+
be distributed entirely under this license, and must not be distributed
71+
under any other license. The requirement for fonts to remain under this
72+
license does not apply to any document created using the Font Software.
73+
74+
TERMINATION
75+
76+
This license becomes null and void if any of the above conditions are not
77+
met.
78+
79+
DISCLAIMER
80+
81+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
82+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
83+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
84+
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
85+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
86+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
87+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
88+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
89+
DEALINGS IN THE FONT SOFTWARE.

REUSE.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,9 @@ path = "toolGenerate/**/**"
9292
precedence = "aggregate"
9393
SPDX-FileCopyrightText = "None"
9494
SPDX-License-Identifier = "CC0-1.0"
95+
96+
[[annotations]]
97+
path = "shell/fonts/ElmsSans-Regular.ttf"
98+
precedence = "aggregate"
99+
SPDX-FileCopyrightText = "2025 The Elms Sans Project Authors"
100+
SPDX-License-Identifier = "OFL-1.1"

frame/dsqmlglobal.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <QLoggingCategory>
1212
#include <QCoreApplication>
13+
#include <QFontDatabase>
1314
#include <QQueue>
1415
#include <QWindow>
1516
#include <QGuiApplication>
@@ -27,6 +28,34 @@ DCORE_USE_NAMESPACE
2728

2829
Q_DECLARE_LOGGING_CATEGORY(dsLog)
2930

31+
namespace {
32+
33+
QString shellDataFontFamily()
34+
{
35+
static QString dataFontFamily;
36+
static bool initialized = false;
37+
38+
if (initialized) {
39+
return dataFontFamily;
40+
}
41+
42+
initialized = true;
43+
const int fontId = QFontDatabase::addApplicationFont(QStringLiteral(":/shell/fonts/ElmsSans-Regular.ttf"));
44+
if (fontId < 0) {
45+
qCWarning(dsLog) << "Failed to load shell data font resource";
46+
return dataFontFamily;
47+
}
48+
49+
const QStringList families = QFontDatabase::applicationFontFamilies(fontId);
50+
if (!families.isEmpty()) {
51+
dataFontFamily = families.constFirst();
52+
}
53+
54+
return dataFontFamily;
55+
}
56+
57+
} // namespace
58+
3059
class DQmlGlobalPrivate : public DObjectPrivate
3160
{
3261
public:
@@ -87,6 +116,11 @@ DApplet *DQmlGlobal::rootApplet() const
87116
return DPluginLoader::instance()->rootApplet();
88117
}
89118

119+
QString DQmlGlobal::dataFontFamily() const
120+
{
121+
return shellDataFontFamily();
122+
}
123+
90124
void DQmlGlobal::singleShot(int msec, QJSValue callback)
91125
{
92126
if (!callback.isCallable()) {

frame/private/dsqmlglobal_p.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class DQmlGlobal : public QObject, public DTK_CORE_NAMESPACE::DObject
2424
Q_OBJECT
2525
D_DECLARE_PRIVATE(DQmlGlobal)
2626
Q_PROPERTY(DApplet* rootApplet READ rootApplet NOTIFY rootAppletChanged FINAL)
27+
Q_PROPERTY(QString dataFontFamily READ dataFontFamily CONSTANT FINAL)
2728
public:
2829
explicit DQmlGlobal(QObject *parent = nullptr);
2930
~DQmlGlobal() override;
@@ -36,6 +37,7 @@ class DQmlGlobal : public QObject, public DTK_CORE_NAMESPACE::DObject
3637
Q_INVOKABLE void singleShot(int msec, QJSValue callback);
3738

3839
DApplet *rootApplet() const;
40+
QString dataFontFamily() const;
3941

4042
static DQmlGlobal *instance();
4143
static QList<QWindow *> allChildrenWindows(QWindow *target);

panels/dock/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,25 @@ add_library(dockpanel SHARED
5959
${dock_panel_sources}
6060
)
6161

62+
add_dependencies(dockpanel tray_loader_font_sync)
63+
64+
add_library(tray_loader_font_sync SHARED
65+
tray_loader_font_sync.cpp
66+
tray_loader_font_sync.qrc
67+
)
68+
69+
set_target_properties(tray_loader_font_sync PROPERTIES
70+
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}"
71+
)
72+
73+
target_link_libraries(tray_loader_font_sync PRIVATE
74+
Qt${QT_VERSION_MAJOR}::Core
75+
Qt${QT_VERSION_MAJOR}::Gui
76+
Qt${QT_VERSION_MAJOR}::Widgets
77+
)
78+
79+
install(TARGETS tray_loader_font_sync DESTINATION "${CMAKE_INSTALL_LIBDIR}/dde-shell")
80+
6281
qt_generate_wayland_protocol_client_sources(dockpanel
6382
NO_INCLUDE_CORE_ONLY
6483
FILES

panels/dock/dockpanel.cpp

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,28 +40,69 @@ constexpr auto kAppearancePath = "/org/deepin/dde/Appearance1";
4040
constexpr auto kAppearanceInterface = "org.deepin.dde.Appearance1";
4141
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties";
4242

43-
ColorTheme colorThemeFromGlobalThemeName(const QString &themeName, const ColorTheme &fallbackTheme)
43+
Dtk::Gui::DGuiApplicationHelper::ColorType explicitThemeTypeFromName(const QString &themeName)
4444
{
45-
if (themeName.endsWith(QStringLiteral(".dark"), Qt::CaseInsensitive))
46-
return Dark;
45+
const QString normalizedThemeName = themeName.trimmed().toLower();
46+
if (normalizedThemeName.isEmpty())
47+
return Dtk::Gui::DGuiApplicationHelper::UnknownType;
4748

48-
if (themeName.endsWith(QStringLiteral(".light"), Qt::CaseInsensitive))
49-
return Light;
49+
if (normalizedThemeName == QStringLiteral("dark")
50+
|| normalizedThemeName.endsWith(QStringLiteral(".dark"))
51+
|| normalizedThemeName.endsWith(QStringLiteral("-dark"))
52+
|| normalizedThemeName.endsWith(QStringLiteral("_dark"))) {
53+
return Dtk::Gui::DGuiApplicationHelper::DarkType;
54+
}
55+
56+
if (normalizedThemeName == QStringLiteral("light")
57+
|| normalizedThemeName.endsWith(QStringLiteral(".light"))
58+
|| normalizedThemeName.endsWith(QStringLiteral("-light"))
59+
|| normalizedThemeName.endsWith(QStringLiteral("_light"))) {
60+
return Dtk::Gui::DGuiApplicationHelper::LightType;
61+
}
5062

51-
return fallbackTheme;
63+
return Dtk::Gui::DGuiApplicationHelper::UnknownType;
5264
}
5365

54-
Dtk::Gui::DGuiApplicationHelper::ColorType helperThemeTypeFromGlobalThemeName(
55-
const QString &themeName,
56-
Dtk::Gui::DGuiApplicationHelper::ColorType fallbackTheme)
66+
Dtk::Gui::DGuiApplicationHelper::ColorType currentEffectiveThemeType(Dtk::Gui::DGuiApplicationHelper *helper)
5767
{
58-
if (themeName.endsWith(QStringLiteral(".dark"), Qt::CaseInsensitive))
59-
return Dtk::Gui::DGuiApplicationHelper::DarkType;
60-
61-
if (themeName.endsWith(QStringLiteral(".light"), Qt::CaseInsensitive))
68+
if (!helper)
6269
return Dtk::Gui::DGuiApplicationHelper::LightType;
6370

64-
return fallbackTheme;
71+
const auto currentThemeType = helper->themeType();
72+
if (currentThemeType != Dtk::Gui::DGuiApplicationHelper::UnknownType)
73+
return currentThemeType;
74+
75+
const auto currentPaletteType = helper->paletteType();
76+
if (currentPaletteType != Dtk::Gui::DGuiApplicationHelper::UnknownType)
77+
return currentPaletteType;
78+
79+
return Dtk::Gui::DGuiApplicationHelper::LightType;
80+
}
81+
82+
Dtk::Gui::DGuiApplicationHelper::ColorType effectiveThemeTypeFromAppearance(
83+
const QString &globalThemeName,
84+
const QString &gtkThemeName,
85+
const QString &iconThemeName,
86+
Dtk::Gui::DGuiApplicationHelper *helper)
87+
{
88+
const auto globalThemeType = explicitThemeTypeFromName(globalThemeName);
89+
if (globalThemeType != Dtk::Gui::DGuiApplicationHelper::UnknownType)
90+
return globalThemeType;
91+
92+
const auto gtkThemeType = explicitThemeTypeFromName(gtkThemeName);
93+
if (gtkThemeType != Dtk::Gui::DGuiApplicationHelper::UnknownType)
94+
return gtkThemeType;
95+
96+
const auto iconThemeType = explicitThemeTypeFromName(iconThemeName);
97+
if (iconThemeType != Dtk::Gui::DGuiApplicationHelper::UnknownType)
98+
return iconThemeType;
99+
100+
return currentEffectiveThemeType(helper);
101+
}
102+
103+
ColorTheme colorThemeFromHelperThemeType(Dtk::Gui::DGuiApplicationHelper::ColorType themeType)
104+
{
105+
return themeType == Dtk::Gui::DGuiApplicationHelper::DarkType ? Dark : Light;
65106
}
66107

67108
QString readAppearanceStringProperty(const QString &propertyName)
@@ -87,7 +128,9 @@ void syncApplicationTheme(Dtk::Gui::DGuiApplicationHelper *helper,
87128
if (!helper)
88129
return;
89130

90-
const auto targetThemeType = helperThemeTypeFromGlobalThemeName(globalThemeName, helper->themeType());
131+
const auto explicitThemeType = explicitThemeTypeFromName(globalThemeName);
132+
const bool followSystemTheme = explicitThemeType == Dtk::Gui::DGuiApplicationHelper::UnknownType;
133+
const auto targetPaletteType = followSystemTheme ? Dtk::Gui::DGuiApplicationHelper::UnknownType : explicitThemeType;
91134

92135
if (auto *applicationTheme = helper->applicationTheme()) {
93136
const QByteArray gtkThemeNameBytes = gtkThemeName.toUtf8();
@@ -101,10 +144,11 @@ void syncApplicationTheme(Dtk::Gui::DGuiApplicationHelper *helper,
101144
}
102145
}
103146

104-
if (helper->paletteType() != targetThemeType) {
105-
helper->setPaletteType(targetThemeType);
147+
if (helper->paletteType() != targetPaletteType) {
148+
helper->setPaletteType(targetPaletteType);
106149
}
107150

151+
const auto targetThemeType = effectiveThemeTypeFromAppearance(globalThemeName, gtkThemeName, iconThemeName, helper);
108152
const QPalette targetPalette = helper->applicationPalette(targetThemeType);
109153
if (helper->applicationPalette() != targetPalette) {
110154
helper->setApplicationPalette(targetPalette);
@@ -353,7 +397,6 @@ void DockPanel::onAppearanceRefreshed(const QString &type)
353397
void DockPanel::syncColorThemeWithSystem()
354398
{
355399
auto *guiHelper = Dtk::Gui::DGuiApplicationHelper::instance();
356-
const auto fallbackTheme = static_cast<ColorTheme>(guiHelper->themeType());
357400
QDBusInterface appearanceProperties(kAppearanceService,
358401
kAppearancePath,
359402
kPropertiesInterface,
@@ -367,13 +410,14 @@ void DockPanel::syncColorThemeWithSystem()
367410
const QString gtkThemeName = readAppearanceStringProperty(QStringLiteral("GtkTheme"));
368411
const QString iconThemeName = readAppearanceStringProperty(QStringLiteral("IconTheme"));
369412
syncApplicationTheme(guiHelper, globalThemeName, gtkThemeName, iconThemeName);
370-
setColorTheme(colorThemeFromGlobalThemeName(globalThemeName, fallbackTheme));
413+
setColorTheme(colorThemeFromHelperThemeType(
414+
effectiveThemeTypeFromAppearance(globalThemeName, gtkThemeName, iconThemeName, guiHelper)));
371415
return;
372416
}
373417
}
374418

375419
syncApplicationTheme(guiHelper, QString(), QString(), QString());
376-
setColorTheme(fallbackTheme);
420+
setColorTheme(colorThemeFromHelperThemeType(currentEffectiveThemeType(guiHelper)));
377421
}
378422

379423
uint DockPanel::dockSize()

panels/dock/environments.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@
55
#pragma once
66

77
#define CMAKE_INSTALL_FULL_LIBEXECDIR "@CMAKE_INSTALL_FULL_LIBEXECDIR@"
8+
#define CMAKE_INSTALL_FULL_LIBDIR "@CMAKE_INSTALL_FULL_LIBDIR@"
89
#define CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
10+
#define TRAY_LOADER_FONT_SYNC_BUILD_PATH "@PROJECT_BINARY_DIR@/libtray_loader_font_sync.so"
11+
#define TRAY_LOADER_FONT_SYNC_INSTALL_PATH "@CMAKE_INSTALL_FULL_LIBDIR@/dde-shell/libtray_loader_font_sync.so"

panels/dock/loadtrayplugins.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,33 @@
1010
#include <DConfig>
1111

1212
#include <QDir>
13+
#include <QFileInfo>
1314
#include <QTimer>
1415
#include <QGuiApplication>
1516

1617
namespace dock {
1718

19+
namespace {
20+
21+
QString trayLoaderFontSyncPath()
22+
{
23+
const QStringList candidates = {
24+
qEnvironmentVariable("TRAY_LOADER_FONT_SYNC_PATH"),
25+
QString::fromLatin1(TRAY_LOADER_FONT_SYNC_BUILD_PATH),
26+
QString::fromLatin1(TRAY_LOADER_FONT_SYNC_INSTALL_PATH)
27+
};
28+
29+
for (const QString &candidate : candidates) {
30+
if (!candidate.isEmpty() && QFileInfo::exists(candidate)) {
31+
return candidate;
32+
}
33+
}
34+
35+
return QString();
36+
}
37+
38+
} // namespace
39+
1840
LoadTrayPlugins::LoadTrayPlugins(QObject *parent)
1941
: QObject(parent)
2042
{
@@ -98,6 +120,15 @@ void LoadTrayPlugins::setProcessEnv(QProcess *process)
98120
// TODO: use protocols to determine the environment instead of environment variables
99121
env.remove("DDE_CURRENT_COMPOSITOR");
100122

123+
const QString fontSyncPath = trayLoaderFontSyncPath();
124+
if (!fontSyncPath.isEmpty()) {
125+
QStringList preloadEntries = env.value(QStringLiteral("LD_PRELOAD")).split(QLatin1Char(':'), Qt::SkipEmptyParts);
126+
if (!preloadEntries.contains(fontSyncPath)) {
127+
preloadEntries.prepend(fontSyncPath);
128+
}
129+
env.insert(QStringLiteral("LD_PRELOAD"), preloadEntries.join(QLatin1Char(':')));
130+
}
131+
101132
process->setProcessEnvironment(env);
102133
}
103134

0 commit comments

Comments
 (0)