kcms/colors: Add an option to apply accent color from wallpaper

This adds an option to set the accent color from the current wallpaper.

The way it works is that it exposes some DBus calls; if a wallpaper plugin
supports wallpaper accent colors then it should say so by this DBus call
when starting up and also should say which wallpaper is being currently
used (for the purpose of extracting an accent color from it) or set an
accent color itself. After that it should keep declaring the wallpaper or
set accent color whenever wallpaper changes or whenever the plugin author
thinks it is appropriate to say so.

There is already an implementation of the color extracting algorithm which
the plugin can either use, or else set whatever accent color it wants. The
necessary DBus calls for the official image and wallpaper plugin are
implemented, so they should work out of the box.

BUG: 444676
FIXED-IN: 5.25
wilder-5.25
Tanbir Jishan 4 years ago committed by Nate Graham
parent 94b9a03ce2
commit 6eb2b52945
  1. 47
      kcms/colors/CMakeLists.txt
  2. 47
      kcms/colors/accentColorService/accentColorService.cpp
  3. 22
      kcms/colors/accentColorService/accentColorService.h
  4. 8
      kcms/colors/accentColorService/accentColorService.json
  5. 41
      kcms/colors/colors.cpp
  6. 14
      kcms/colors/colors.h
  7. 4
      kcms/colors/colorssettings.kcfg
  8. 2
      kcms/colors/colorssettings.kcfgc
  9. 50
      kcms/colors/package/contents/ui/main.qml
  10. 3
      shell/CMakeLists.txt
  11. 6
      shell/dbus/org.kde.PlasmaShell.xml
  12. 28
      shell/desktopview.cpp
  13. 6
      shell/desktopview.h
  14. 13
      shell/shellcorona.cpp
  15. 2
      shell/shellcorona.h

@ -9,6 +9,30 @@ set(kcm_colors_SRCS
filterproxymodel.cpp filterproxymodel.cpp
) )
qt5_generate_dbus_interface(
accentColorService/accentColorService.h
org.kde.plasmashell.accentColor.xml
OPTIONS -M
)
set(plasma-accentcolor-service_SRCS
accentColorService/accentColorService.cpp
colorsapplicator.cpp
colorsmodel.cpp
../kcms-common.cpp
../krdb/krdb.cpp
)
set(plasma-accentcolor-service_SRCS
${plasma-accentcolor-service_SRCS}
${CMAKE_CURRENT_BINARY_DIR}/org.kde.plasmashell.accentColor.xml
)
qt5_add_dbus_adaptor(plasma-accentcolor-service_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.plasmashell.accentColor.xml
accentColorService/accentColorService.h AccentColorService
accentcolor_service_adaptor AccentColorServiceAdaptor)
kcmutils_generate_module_data( kcmutils_generate_module_data(
kcm_colors_SRCS kcm_colors_SRCS
MODULE_DATA_HEADER colorsdata.h MODULE_DATA_HEADER colorsdata.h
@ -54,8 +78,10 @@ set(plasma-apply-colorscheme_SRCS
) )
kconfig_add_kcfg_files(plasma-apply-colorscheme_SRCS colorssettings.kcfgc GENERATE_MOC) kconfig_add_kcfg_files(plasma-apply-colorscheme_SRCS colorssettings.kcfgc GENERATE_MOC)
kconfig_add_kcfg_files(plasma-accentcolor-service_SRCS colorssettings.kcfgc GENERATE_MOC)
add_executable(plasma-apply-colorscheme ${plasma-apply-colorscheme_SRCS}) add_executable(plasma-apply-colorscheme ${plasma-apply-colorscheme_SRCS})
kcoreaddons_add_plugin(plasma-accentcolor-service SOURCES ${plasma-accentcolor-service_SRCS} INSTALL_NAMESPACE "kf${QT_MAJOR_VERSION}/kded")
target_link_libraries(plasma-apply-colorscheme target_link_libraries(plasma-apply-colorscheme
Qt::Core Qt::Core
@ -68,12 +94,33 @@ target_link_libraries(plasma-apply-colorscheme
PW::KWorkspace PW::KWorkspace
X11::X11 X11::X11
) )
target_link_libraries(plasma-accentcolor-service
Qt::Core
Qt::DBus
KF5::GuiAddons
KF5::KCMUtils
KF5::I18n
KF5::WindowSystem
KF5::ConfigCore
KF5::DBusAddons
PW::KWorkspace
X11::X11
)
if (QT_MAJOR_VERSION EQUAL "5") if (QT_MAJOR_VERSION EQUAL "5")
target_link_libraries(plasma-apply-colorscheme Qt::X11Extras) target_link_libraries(plasma-apply-colorscheme Qt::X11Extras)
else() else()
target_link_libraries(plasma-apply-colorscheme Qt::GuiPrivate) target_link_libraries(plasma-apply-colorscheme Qt::GuiPrivate)
endif() endif()
if (QT_MAJOR_VERSION EQUAL "5")
target_link_libraries(plasma-accentcolor-service Qt::X11Extras)
else()
target_link_libraries(plasma-accentcolor-service Qt::GuiPrivate)
endif()
install(FILES colorssettings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) install(FILES colorssettings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
install(FILES kcm_colors.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES kcm_colors.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(TARGETS plasma-apply-colorscheme DESTINATION ${KDE_INSTALL_BINDIR}) install(TARGETS plasma-apply-colorscheme DESTINATION ${KDE_INSTALL_BINDIR})

@ -0,0 +1,47 @@
#include <KPluginFactory>
#include <QDBusConnection>
#include "../../kcms-common_p.h"
#include "accentColorService.h"
#include "accentcolor_service_adaptor.h"
#include "colorsapplicator.h"
K_PLUGIN_CLASS_WITH_JSON(AccentColorService, "accentColorService.json")
AccentColorService::AccentColorService(QObject *parent, const QList<QVariant> &)
: KDEDModule(parent)
, m_settings(new ColorsSettings(this))
, m_model(new ColorsModel(this))
{
new AccentColorServiceAdaptor(this);
QDBusConnection dbus = QDBusConnection::sessionBus();
dbus.registerObject("/AccentColor", this);
dbus.registerService("org.kde.plasmashell.accentColor");
}
void AccentColorService::setAccentColor(const QString &accentColor)
{
m_settings->load();
if (QColor::isValidColor(accentColor) && m_settings->accentColorFromWallpaper()) {
m_model->load();
m_model->setSelectedScheme(m_settings->colorScheme());
const QString path =
QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/%1.colors").arg(m_model->selectedScheme()));
auto msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
QStringLiteral("/org/kde/KWin/BlendChanges"),
QStringLiteral("org.kde.KWin.BlendChanges"),
QStringLiteral("start"));
msg << 300;
// This is deliberately blocking so that we ensure Kwin has processed the
// animation start event before we potentially trigger client side changes
QDBusConnection::sessionBus().call(msg);
m_settings->setAccentColor(accentColor);
m_settings->save();
applyScheme(path, m_settings->config(), KConfig::Notify);
notifyKcmChange(GlobalChangeType::PaletteChanged);
}
}
#include "accentColorService.moc"

@ -0,0 +1,22 @@
#pragma once
#include "colorsmodel.h"
#include "colorssettings.h"
#include <kdedmodule.h>
class AccentColorService : public KDEDModule
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.plasmashell.accentColor")
public:
explicit AccentColorService(QObject *parent, const QList<QVariant> &);
public Q_SLOTS:
void setAccentColor(const QString &color);
private:
ColorsSettings *m_settings;
ColorsModel *m_model;
};

@ -0,0 +1,8 @@
{
"KPlugin": {
"Description": "Applies extracted accent color from wallpaper on dbus request",
"Name": "accentColorService"
},
"X-KDE-FactoryName": "accentColorService",
"X-KDE-Kded-autoload": true
}

@ -13,6 +13,8 @@
#include <QColor> #include <QColor>
#include <QDBusConnection> #include <QDBusConnection>
#include <QDBusMessage> #include <QDBusMessage>
#include <QDBusPendingCall>
#include <QDBusReply>
#include <QFileInfo> #include <QFileInfo>
#include <QGuiApplication> #include <QGuiApplication>
#include <QProcess> #include <QProcess>
@ -55,6 +57,7 @@ KCMColors::KCMColors(QObject *parent, const KPluginMetaData &data, const QVarian
, m_filteredModel(new FilterProxyModel(this)) , m_filteredModel(new FilterProxyModel(this))
, m_data(new ColorsData(this)) , m_data(new ColorsData(this))
, m_config(KSharedConfig::openConfig(QStringLiteral("kdeglobals"))) , m_config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")))
, m_configWatcher(KConfigWatcher::create(m_config))
{ {
auto uri = "org.kde.private.kcms.colors"; auto uri = "org.kde.private.kcms.colors";
qmlRegisterUncreatableType<KCMColors>(uri, 1, 0, "KCM", QStringLiteral("Cannot create instances of KCM")); qmlRegisterUncreatableType<KCMColors>(uri, 1, 0, "KCM", QStringLiteral("Cannot create instances of KCM"));
@ -77,6 +80,14 @@ KCMColors::KCMColors(QObject *parent, const KPluginMetaData &data, const QVarian
connect(m_model, &ColorsModel::selectedSchemeChanged, m_filteredModel, &FilterProxyModel::setSelectedScheme); connect(m_model, &ColorsModel::selectedSchemeChanged, m_filteredModel, &FilterProxyModel::setSelectedScheme);
m_filteredModel->setSourceModel(m_model); m_filteredModel->setSourceModel(m_model);
// Since the accent color can now change from somewhere else, we need to update the view accordingly.
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) {
if (group.name() == QLatin1String("General") && names.contains(QByteArrayLiteral("AccentColor"))) {
colorsSettings()->save(); // We need to first save the local changes, if any.
colorsSettings()->load();
}
});
} }
KCMColors::~KCMColors() KCMColors::~KCMColors()
@ -123,6 +134,16 @@ void KCMColors::setAccentColor(const QColor &accentColor)
Q_EMIT settingsChanged(); Q_EMIT settingsChanged();
} }
bool KCMColors::applyAccentColorFromWallpaper() const
{
return colorsSettings()->accentColorFromWallpaper();
}
void KCMColors::setApplyAccentColorFromWallpaper(bool boolean)
{
colorsSettings()->setAccentColorFromWallpaper(boolean);
Q_EMIT settingsChanged();
}
bool KCMColors::downloadingFile() const bool KCMColors::downloadingFile() const
{ {
return m_tempCopyJob; return m_tempCopyJob;
@ -380,6 +401,7 @@ void KCMColors::saveColors()
auto setGlobals = [=]() { auto setGlobals = [=]() {
globalConfig->group("General").writeEntry("AccentColor", QColor()); globalConfig->group("General").writeEntry("AccentColor", QColor());
globalConfig->group("General").writeEntry("accentColorFromWallpaper", applyAccentColorFromWallpaper(), KConfig::Notify);
if (accentColor() != QColor(Qt::transparent)) { if (accentColor() != QColor(Qt::transparent)) {
globalConfig->group("General").writeEntry("AccentColor", accentColor(), KConfig::Notify); globalConfig->group("General").writeEntry("AccentColor", accentColor(), KConfig::Notify);
} else { } else {
@ -403,6 +425,25 @@ QColor KCMColors::accentForeground(const QColor &accent, const bool &isActive)
return ::accentForeground(accent, isActive); return ::accentForeground(accent, isActive);
} }
void KCMColors::applyWallpaperAccentColor()
{
QDBusMessage accentColor = QDBusMessage::createMethodCall("org.kde.plasmashell", "/PlasmaShell", "org.kde.PlasmaShell", "color");
auto const connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "accentColorBus");
QDBusPendingCall async = connection.asyncCall(accentColor);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher *)), this, SLOT(wallpaperAccentColorArrivedSlot(QDBusPendingCallWatcher *)));
}
void KCMColors::wallpaperAccentColorArrivedSlot(QDBusPendingCallWatcher *call)
{
QDBusPendingReply<QString> reply = *call;
if (!reply.isError()) {
setAccentColor(QColor(reply.value()));
}
call->deleteLater();
}
void KCMColors::processPendingDeletions() void KCMColors::processPendingDeletions()
{ {
const QStringList pendingDeletions = m_model->pendingDeletions(); const QStringList pendingDeletions = m_model->pendingDeletions();

@ -7,8 +7,10 @@
#pragma once #pragma once
#include <KConfigWatcher>
#include <KNSCore/EntryWrapper> #include <KNSCore/EntryWrapper>
#include <QColor> #include <QColor>
#include <QDBusPendingCallWatcher>
#include <QPointer> #include <QPointer>
#include <QScopedPointer> #include <QScopedPointer>
@ -40,8 +42,9 @@ class KCMColors : public KQuickAddons::ManagedConfigModule
Q_PROPERTY(FilterProxyModel *filteredModel READ filteredModel CONSTANT) Q_PROPERTY(FilterProxyModel *filteredModel READ filteredModel CONSTANT)
Q_PROPERTY(ColorsSettings *colorsSettings READ colorsSettings CONSTANT) Q_PROPERTY(ColorsSettings *colorsSettings READ colorsSettings CONSTANT)
Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged) Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged)
Q_PROPERTY(QColor accentColor READ accentColor WRITE setAccentColor NOTIFY accentColorChanged) Q_PROPERTY(QColor accentColor READ accentColor WRITE setAccentColor NOTIFY accentColorChanged)
Q_PROPERTY(bool applyAccentColorFromWallpaper READ applyAccentColorFromWallpaper WRITE setApplyAccentColorFromWallpaper NOTIFY
applyAccentColorFromWallpaperChanged)
public: public:
KCMColors(QObject *parent, const KPluginMetaData &data, const QVariantList &args); KCMColors(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
@ -66,6 +69,10 @@ public:
void setAccentColor(const QColor &accentColor); void setAccentColor(const QColor &accentColor);
void resetAccentColor(); void resetAccentColor();
Q_SIGNAL void accentColorChanged(); Q_SIGNAL void accentColorChanged();
Q_SIGNAL void applyAccentColorFromWallpaperChanged();
bool applyAccentColorFromWallpaper() const;
void setApplyAccentColorFromWallpaper(bool boolean);
Q_INVOKABLE void installSchemeFromFile(const QUrl &url); Q_INVOKABLE void installSchemeFromFile(const QUrl &url);
@ -76,11 +83,15 @@ public:
Q_INVOKABLE QColor tinted(const QColor& color, const QColor& accent, bool tints, qreal tintFactor); Q_INVOKABLE QColor tinted(const QColor& color, const QColor& accent, bool tints, qreal tintFactor);
Q_INVOKABLE QColor accentBackground(const QColor &accent, const QColor &background); Q_INVOKABLE QColor accentBackground(const QColor &accent, const QColor &background);
Q_INVOKABLE QColor accentForeground(const QColor &accent, const bool &isActive); Q_INVOKABLE QColor accentForeground(const QColor &accent, const bool &isActive);
Q_INVOKABLE void applyWallpaperAccentColor();
public Q_SLOTS: public Q_SLOTS:
void load() override; void load() override;
void save() override; void save() override;
private Q_SLOTS:
void wallpaperAccentColorArrivedSlot(QDBusPendingCallWatcher *call);
Q_SIGNALS: Q_SIGNALS:
void downloadingFileChanged(); void downloadingFileChanged();
@ -107,6 +118,7 @@ private:
QProcess *m_editDialogProcess = nullptr; QProcess *m_editDialogProcess = nullptr;
KSharedConfigPtr m_config; KSharedConfigPtr m_config;
KConfigWatcher::Ptr m_configWatcher;
QScopedPointer<QTemporaryFile> m_tempInstallFile; QScopedPointer<QTemporaryFile> m_tempInstallFile;
QPointer<KIO::FileCopyJob> m_tempCopyJob; QPointer<KIO::FileCopyJob> m_tempCopyJob;

@ -13,5 +13,9 @@
<label>Accent color</label> <label>Accent color</label>
<default>transparent</default> <default>transparent</default>
</entry> </entry>
<entry name="accentColorFromWallpaper" key="accentColorFromWallpaper" type="Bool">
<label>Whether accent color from wallpaper should be applied</label>
<default>false</default>
</entry>
</group> </group>
</kcfg> </kcfg>

@ -4,4 +4,4 @@ Mutators=true
DefaultValueGetters=true DefaultValueGetters=true
GenerateProperties=true GenerateProperties=true
ParentInConstructor=true ParentInConstructor=true
Notifiers=colorScheme Notifiers=colorScheme, accentColor

@ -39,6 +39,13 @@ KCM.GridViewKCM {
restoreMode: Binding.RestoreBinding restoreMode: Binding.RestoreBinding
} }
Binding {
target: kcm
property: "applyAccentColorFromWallpaper"
value: wallpaperAccentBox.checked
restoreMode: Binding.RestoreBinding
}
KCM.SettingStateBinding { KCM.SettingStateBinding {
configObject: kcm.colorsSettings configObject: kcm.colorsSettings
settingName: "colorScheme" settingName: "colorScheme"
@ -134,7 +141,7 @@ KCM.GridViewKCM {
Layout.fillWidth: true Layout.fillWidth: true
QtControls.ButtonGroup { QtControls.ButtonGroup {
buttons: [notAccentBox, accentBox] buttons: [notAccentBox, wallpaperAccentBox, accentBox]
} }
QtControls.RadioButton { QtControls.RadioButton {
@ -142,7 +149,7 @@ KCM.GridViewKCM {
Kirigami.FormData.label: i18n("Use accent color:") Kirigami.FormData.label: i18n("Use accent color:")
text: i18n("From current color scheme") text: i18n("From current color scheme")
checked: Qt.colorEqual(kcm.accentColor, "transparent") checked: Qt.colorEqual(kcm.accentColor, "transparent") && !kcm.applyAccentColorFromWallpaper
onToggled: { onToggled: {
if (enabled) { if (enabled) {
@ -150,18 +157,45 @@ KCM.GridViewKCM {
} }
} }
} }
QtControls.RadioButton {
id: wallpaperAccentBox
text: i18nc("@option:radio wallpaper accent color option", "From current wallpaper")
checked: kcm.applyAccentColorFromWallpaper
onToggled: {
if (enabled) {
kcm.applyWallpaperAccentColor();
}
}
}
RowLayout { RowLayout {
spacing: 0 spacing: 0
QtControls.RadioButton { QtControls.RadioButton {
id: accentBox id: accentBox
checked: !Qt.colorEqual(kcm.accentColor, "transparent") checked: !Qt.colorEqual(kcm.accentColor, "transparent") && !kcm.applyAccentColorFromWallpaper
onToggled: { onToggled: {
if (enabled) { if (enabled) {
kcm.accentColor = colorRepeater.model[0] kcm.accentColor = colorRepeater.model[0]
} }
} }
/* This required when someone directly clicks one of the accent color buttons or the color picker instead
* of first checking this button. Failing to call this function in those situations will leave this button unchecked
* which was the previous behaviour.
* NOTE: Currently user is able to dicrectly toggle the accentColor buttons or the color picker. If in future the situation
* becomes such that the user must toggle this button first then just remove all the occurrences of this function
*/
function restartBindingWithCheckedAsTrue() {
if(!accentBox.checked) {
accentBox.checked = true
accentBox.checked = Qt.binding(() => !Qt.colorEqual(kcm.accentColor, "transparent") && !kcm.applyAccentColorFromWallpaper)
}
}
} }
RowLayout { RowLayout {
spacing: accentBox.spacing spacing: accentBox.spacing
component ColorRadioButton : T.RadioButton { component ColorRadioButton : T.RadioButton {
@ -198,7 +232,7 @@ KCM.GridViewKCM {
MouseArea { MouseArea {
enabled: false enabled: false
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: accentBox.checked ? Qt.PointingHandCursor : Qt.ArrowCursor
} }
} }
@ -223,9 +257,10 @@ KCM.GridViewKCM {
checked: Qt.colorEqual(kcm.accentColor, modelData) checked: Qt.colorEqual(kcm.accentColor, modelData)
onToggled: { onToggled: {
accentBox.restartBindingWithCheckedAsTrue()
kcm.accentColor = modelData kcm.accentColor = modelData
checked = Qt.binding(() => Qt.colorEqual(kcm.accentColor, modelData)); checked = Qt.binding(() => Qt.colorEqual(kcm.accentColor, modelData));
} }
} }
} }
@ -243,6 +278,7 @@ KCM.GridViewKCM {
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
color: kcm.accentColor color: kcm.accentColor
onAccepted: { onAccepted: {
accentBox.restartBindingWithCheckedAsTrue()
kcm.accentColor = colorDialog.color kcm.accentColor = colorDialog.color
} }
} }
@ -254,7 +290,7 @@ KCM.GridViewKCM {
!colorRepeater.model.some(color => Qt.colorEqual(color, root.accentColor)) !colorRepeater.model.some(color => Qt.colorEqual(color, root.accentColor))
: false : false
/* The qt binding will keep the binding alive as well as uncheck the button /* The qt binding will keep the binding alive as well as uncheck the button
* we can't just disable the button because then the icon will become grey * we can't just disable the button because then the icon will become grey
* and also we have to provide a MouseArea for interaction. Both of these * and also we have to provide a MouseArea for interaction. Both of these
* can be done with the button being disabled but it will become very * can be done with the button being disabled but it will become very
@ -265,7 +301,7 @@ KCM.GridViewKCM {
colorDialog.open() colorDialog.open()
} }
color: isCustomColor ? kcm.accentColor : "transparent" color: isCustomColor && accentBox.checked ? kcm.accentColor : "transparent"
checked: isCustomColor checked: isCustomColor
onClicked: openColorDialog() onClicked: openColorDialog()

@ -57,6 +57,8 @@ if (TARGET KUserFeedbackCore)
) )
endif() endif()
kconfig_add_kcfg_files(plasma_shell_SRCS ../kcms/colors/colorssettings.kcfgc GENERATE_MOC)
add_executable(plasmashell) add_executable(plasmashell)
if (QT_MAJOR_VERSION EQUAL "5") if (QT_MAJOR_VERSION EQUAL "5")
ecm_add_qtwayland_client_protocol(plasma_shell_SRCS ecm_add_qtwayland_client_protocol(plasma_shell_SRCS
@ -96,6 +98,7 @@ target_link_libraries(plasmashell
KF5::Package KF5::Package
KF5::WaylandClient KF5::WaylandClient
KF5::Notifications KF5::Notifications
KF5::GuiAddons
PW::KWorkspace PW::KWorkspace
Wayland::Client Wayland::Client
) )

@ -15,6 +15,12 @@
<arg name="script" type="s" direction="in"/> <arg name="script" type="s" direction="in"/>
<arg name="output" type="s" direction="out"/> <arg name="output" type="s" direction="out"/>
</method> </method>
<method name="color">
<arg name="output" type="s" direction="out"/>
</method>
<signal name="colorChanged">
<arg name="changedColor" type="s" direction="out"/>
</signal>
<method name="dumpCurrentLayoutJS"> <method name="dumpCurrentLayoutJS">
<arg name="script" type="ay" direction="out"/> <arg name="script" type="ay" direction="out"/>
</method> </method>

@ -9,6 +9,8 @@
#include "krunner_interface.h" #include "krunner_interface.h"
#include "shellcorona.h" #include "shellcorona.h"
#include <QDBusConnection>
#include <QDBusMessage>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlEngine> #include <QQmlEngine>
#include <QQuickItem> #include <QQuickItem>
@ -34,6 +36,7 @@
DesktopView::DesktopView(Plasma::Corona *corona, QScreen *targetScreen) DesktopView::DesktopView(Plasma::Corona *corona, QScreen *targetScreen)
: PlasmaQuick::ContainmentView(corona, nullptr) : PlasmaQuick::ContainmentView(corona, nullptr)
, m_accentColor("transparent")
, m_windowType(Desktop) , m_windowType(Desktop)
, m_shellSurface(nullptr) , m_shellSurface(nullptr)
{ {
@ -55,6 +58,7 @@ DesktopView::DesktopView(Plasma::Corona *corona, QScreen *targetScreen)
setSource(corona->kPackage().fileUrl("views", QStringLiteral("Desktop.qml"))); setSource(corona->kPackage().fileUrl("views", QStringLiteral("Desktop.qml")));
connect(this, &QWindow::screenChanged, this, &DesktopView::adaptToScreen); connect(this, &QWindow::screenChanged, this, &DesktopView::adaptToScreen);
connect(this, &DesktopView::accentColorChanged, this, &DesktopView::setAccentColorFromWallpaper);
QObject::connect(corona, &Plasma::Corona::kPackageChanged, this, &DesktopView::coronaPackageChanged); QObject::connect(corona, &Plasma::Corona::kPackageChanged, this, &DesktopView::coronaPackageChanged);
@ -125,6 +129,19 @@ void DesktopView::adaptToScreen()
m_oldScreen = m_screenToFollow; m_oldScreen = m_screenToFollow;
} }
QString DesktopView::accentColor() const
{
return m_accentColor;
}
void DesktopView::setAccentColor(const QString &accentColor)
{
if (accentColor != m_accentColor) {
m_accentColor = accentColor;
Q_EMIT accentColorChanged(m_accentColor);
}
}
DesktopView::WindowType DesktopView::windowType() const DesktopView::WindowType DesktopView::windowType() const
{ {
return m_windowType; return m_windowType;
@ -372,3 +389,14 @@ void DesktopView::setupWaylandIntegration()
m_shellSurface->setPosition(m_screenToFollow->geometry().topLeft()); m_shellSurface->setPosition(m_screenToFollow->geometry().topLeft());
} }
} }
void DesktopView::setAccentColorFromWallpaper(const QString &accentColor)
{
auto const notPrimaryDisplay = containment()->screen() != 0;
if (notPrimaryDisplay) {
return;
}
QDBusMessage applyAccentColor = QDBusMessage::createMethodCall("org.kde.plasmashell.accentColor", "/AccentColor", "", "setAccentColor");
applyAccentColor << accentColor;
QDBusConnection::sessionBus().send(applyAccentColor);
}

@ -30,6 +30,7 @@ class DesktopView : public PlasmaQuick::ContainmentView
Q_PROPERTY(SessionType sessionType READ sessionType CONSTANT) Q_PROPERTY(SessionType sessionType READ sessionType CONSTANT)
Q_PROPERTY(QVariantMap candidateContainments READ candidateContainmentsGraphicItems NOTIFY candidateContainmentsChanged) Q_PROPERTY(QVariantMap candidateContainments READ candidateContainmentsGraphicItems NOTIFY candidateContainmentsChanged)
Q_PROPERTY(QString accentColor READ accentColor WRITE setAccentColor NOTIFY accentColorChanged)
public: public:
enum WindowType { enum WindowType {
@ -57,6 +58,8 @@ public:
void adaptToScreen(); void adaptToScreen();
void showEvent(QShowEvent *) override; void showEvent(QShowEvent *) override;
QString accentColor() const;
void setAccentColor(const QString &);
WindowType windowType() const; WindowType windowType() const;
void setWindowType(WindowType type); void setWindowType(WindowType type);
@ -85,13 +88,16 @@ Q_SIGNALS:
void windowTypeChanged(); void windowTypeChanged();
void candidateContainmentsChanged(); void candidateContainmentsChanged();
void geometryChanged(); void geometryChanged();
void accentColorChanged(const QString &accentColor);
private: private:
void coronaPackageChanged(const KPackage::Package &package); void coronaPackageChanged(const KPackage::Package &package);
void ensureWindowType(); void ensureWindowType();
void setupWaylandIntegration(); void setupWaylandIntegration();
void setAccentColorFromWallpaper(const QString &accentColor);
bool handleKRunnerTextInput(QKeyEvent *e); bool handleKRunnerTextInput(QKeyEvent *e);
QString m_accentColor;
QPointer<PlasmaQuick::ConfigView> m_configView; QPointer<PlasmaQuick::ConfigView> m_configView;
QPointer<QScreen> m_oldScreen; QPointer<QScreen> m_oldScreen;
QPointer<QScreen> m_screenToFollow; QPointer<QScreen> m_screenToFollow;

@ -739,6 +739,7 @@ void ShellCorona::load()
connect(m_screenPool, &ScreenPool::screenAdded, this, &ShellCorona::addOutput, Qt::UniqueConnection); connect(m_screenPool, &ScreenPool::screenAdded, this, &ShellCorona::addOutput, Qt::UniqueConnection);
connect(m_screenPool, &ScreenPool::screenRemoved, this, &ShellCorona::handleScreenRemoved, Qt::UniqueConnection); connect(m_screenPool, &ScreenPool::screenRemoved, this, &ShellCorona::handleScreenRemoved, Qt::UniqueConnection);
connect(m_screenPool, &ScreenPool::primaryScreenChanged, this, &ShellCorona::primaryScreenChanged, Qt::UniqueConnection); connect(m_screenPool, &ScreenPool::primaryScreenChanged, this, &ShellCorona::primaryScreenChanged, Qt::UniqueConnection);
connect(m_desktopViewForScreen[m_screenPool->primaryScreen()], &DesktopView::accentColorChanged, this, &ShellCorona::colorChanged);
if (!m_waitingPanels.isEmpty()) { if (!m_waitingPanels.isEmpty()) {
m_waitingPanelsTimer.start(); m_waitingPanelsTimer.start();
@ -782,6 +783,9 @@ void ShellCorona::primaryScreenChanged(QScreen *oldPrimary, QScreen *newPrimary)
// can't do the screen invariant here as reconsideroutputs wasn't executed yet // can't do the screen invariant here as reconsideroutputs wasn't executed yet
// CHECK_SCREEN_INVARIANTS // CHECK_SCREEN_INVARIANTS
// refresh the accent color signal binding
connect(m_desktopViewForScreen[m_screenPool->primaryScreen()], &DesktopView::accentColorChanged, this, &ShellCorona::colorChanged);
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -1419,6 +1423,15 @@ void ShellCorona::toggleDashboard()
setDashboardShown(!KWindowSystem::showingDesktop()); setDashboardShown(!KWindowSystem::showingDesktop());
} }
QString ShellCorona::color() const
{
auto const primaryDesktopViewExists = m_desktopViewForScreen.contains(m_screenPool->primaryScreen());
if (primaryDesktopViewExists) {
return m_desktopViewForScreen[m_screenPool->primaryScreen()]->accentColor();
}
return QStringLiteral("#00FFFFFF");
}
QString ShellCorona::evaluateScript(const QString &script) QString ShellCorona::evaluateScript(const QString &script)
{ {
if (calledFromDBus()) { if (calledFromDBus()) {

@ -129,6 +129,7 @@ Q_SIGNALS:
void glInitializationFailed(); void glInitializationFailed();
// A preview for this containment has been rendered and saved to disk // A preview for this containment has been rendered and saved to disk
void containmentPreviewReady(Plasma::Containment *containment, const QString &path); void containmentPreviewReady(Plasma::Containment *containment, const QString &path);
void colorChanged(const QString &color);
public Q_SLOTS: public Q_SLOTS:
/** /**
@ -153,6 +154,7 @@ public Q_SLOTS:
void toggleWidgetExplorer(); void toggleWidgetExplorer();
QString evaluateScript(const QString &string); QString evaluateScript(const QString &string);
void activateLauncherMenu(); void activateLauncherMenu();
QString color() const;
QByteArray dumpCurrentLayoutJS() const; QByteArray dumpCurrentLayoutJS() const;

Loading…
Cancel
Save