support background painting based on window scheme

--support painting based on the active window scheme.
Added a schemecolors class for this and updated
abstractwindowinterface to provide tracking for windows
color schemes.
pull/3/head
Michail Vourlakos 6 years ago
parent 7fd9cb1952
commit f6b4aa55cf

@ -18,6 +18,7 @@ set(lattedock-app_SRCS
importer.cpp
infoview.cpp
launcherssignals.cpp
schemecolors.cpp
layoutsDelegates/checkboxdelegate.cpp
layoutsDelegates/colorcmbboxdelegate.cpp
layoutsDelegates/colorcmbboxitemdelegate.cpp

@ -32,10 +32,24 @@ namespace Latte {
AbstractWindowInterface::AbstractWindowInterface(QObject *parent)
: QObject(parent)
{
QString defaultSchemePath = SchemeColors::possibleSchemeFile("kdeglobals");
SchemeColors *dScheme = new SchemeColors(this, defaultSchemePath);
m_schemes["kdeglobals"] = dScheme;
m_schemes[defaultSchemePath] = dScheme;
connect(this, &AbstractWindowInterface::windowRemoved, this, [&](WindowId wid) {
m_windowScheme.remove(wid);
});
}
AbstractWindowInterface::~AbstractWindowInterface()
{
m_windowScheme.clear();
//! it is just a reference to a real scheme file
m_schemes.take("kdeglobals");
qDeleteAll(m_schemes);
m_schemes.clear();
}
void AbstractWindowInterface::addDock(WindowId wid)
@ -51,5 +65,40 @@ void AbstractWindowInterface::removeDock(WindowId wid)
m_docks.erase(it);
}
//! Scheme support for windows
SchemeColors *AbstractWindowInterface::schemeForWindow(WindowId wid)
{
if (!m_windowScheme.contains(wid)) {
return m_schemes["kdeglobals"];
} else {
return m_schemes[m_windowScheme[wid]];
}
return nullptr;
}
void AbstractWindowInterface::setColorSchemeForWindow(WindowId wid, QString scheme)
{
if (scheme == "kdeglobals" && !m_windowScheme.contains(wid)) {
//default scheme does not have to be set
return;
}
if (scheme == "kdeglobals") {
//! a window that previously had an explicit set scheme now is set back to default scheme
m_windowScheme.remove(wid);
} else {
QString schemeFile = SchemeColors::possibleSchemeFile(scheme);
if (!m_schemes.contains(schemeFile)) {
//! when this scheme file has not been loaded yet
m_schemes[schemeFile] = new SchemeColors(this, schemeFile);
}
m_windowScheme[wid] = schemeFile;
}
}
}

@ -21,6 +21,7 @@
#ifndef ABSTRACTWINDOWINTERFACE_H
#define ABSTRACTWINDOWINTERFACE_H
#include "schemecolors.h"
#include "windowinfowrap.h"
#include "../liblattedock/dock.h"
#include "../liblattedock/extras.h"
@ -31,6 +32,7 @@
#include <QObject>
#include <QWindow>
#include <QDialog>
#include <QMap>
#include <QRect>
#include <QPointer>
#include <QScreen>
@ -83,6 +85,9 @@ public:
void addDock(WindowId wid);
void removeDock(WindowId wid);
SchemeColors *schemeForWindow(WindowId wId);
void setColorSchemeForWindow(WindowId wId, QString scheme);
signals:
void activeWindowChanged(WindowId wid);
void windowChanged(WindowId winfo);
@ -95,6 +100,14 @@ protected:
std::list<WindowId> m_windows;
std::list<WindowId> m_docks;
QPointer<KActivities::Consumer> m_activities;
private:
//! scheme file and its loaded colors
QMap<QString, SchemeColors *> m_schemes;
//! window id and its corresponding scheme file
QMap<WindowId, QString> m_windowScheme;
};
// namespace alias

@ -7,6 +7,9 @@
<arg name="identifier" type="s" direction="in"/>
<arg name="value" type="s" direction="in"/>
</method>
<method name="windowColorScheme">
<arg name="windowIdAndScheme" type="s" direction="in"/>
</method>
<method name="switchToLayout">
<arg name="layout" type="s" direction="in"/>
</method>

@ -777,6 +777,17 @@ void VisibilityManagerPrivate::setExistsWindowSnapped(bool windowSnapped)
emit q->existsWindowSnappedChanged();
}
void VisibilityManagerPrivate::setTouchingWindowScheme(SchemeColors *scheme)
{
if (touchingScheme == scheme) {
return;
}
touchingScheme = scheme;
emit q->touchingWindowSchemeChanged();
}
void VisibilityManagerPrivate::updateAvailableScreenGeometry()
{
if (!view || !view->containment()) {
@ -854,6 +865,8 @@ void VisibilityManagerPrivate::updateDynamicBackgroundWindowFlags()
//! the notification window is not sending a remove signal and creates windows of geometry (0x0 0,0),
//! maybe a garbage collector here is a good idea!!!
bool existsFaultyWindow{false};
WindowId maxWinId;
WindowId snapWinId;
for (const auto &winfo : windows) {
if (winfo.isValid() && !winfo.isMinimized() && wm->isOnCurrentDesktop(winfo.wid()) && wm->isOnCurrentActivity(winfo.wid())) {
@ -861,6 +874,7 @@ void VisibilityManagerPrivate::updateDynamicBackgroundWindowFlags()
//! updated implementation to identify the screen that the maximized window is present
//! in order to avoid: https://bugs.kde.org/show_bug.cgi?id=397700
foundMaximized = true;
maxWinId = winfo.wid();
}
bool touchingPanelEdge{false};
@ -883,6 +897,7 @@ void VisibilityManagerPrivate::updateDynamicBackgroundWindowFlags()
if (((winfo.isActive() || winfo.isKeepAbove()) && touchingPanelEdge)
|| (!winfo.isActive() && snappedWindowsGeometries.contains(winfo.geometry()))) {
foundSnap = true;
snapWinId = winfo.wid();
}
}
@ -906,6 +921,17 @@ void VisibilityManagerPrivate::updateDynamicBackgroundWindowFlags()
setExistsWindowMaximized(foundMaximized);
setExistsWindowSnapped(foundSnap);
//! update color scheme for touching window
if (foundSnap) {
//! first the snap one because that would mean it is active
setTouchingWindowScheme(wm->schemeForWindow(snapWinId));
} else if (foundMaximized) {
setTouchingWindowScheme(wm->schemeForWindow(maxWinId));
} else {
setTouchingWindowScheme(nullptr);
}
}
//! KWin Edges Support functions
@ -1109,6 +1135,11 @@ bool VisibilityManager::existsWindowSnapped() const
return d->windowIsSnappedFlag;
}
SchemeColors *VisibilityManager::touchingWindowScheme() const
{
return d->touchingScheme;
}
//! KWin Edges Support functions
bool VisibilityManager::enableKWinEdges() const
{

@ -22,6 +22,8 @@
#define VISIBILITYMANAGER_H
#include "../plasmaquick/containmentview.h"
#include "../schemecolors.h"
#include "../windowinfowrap.h"
#include "../../liblattedock/dock.h"
#include <QObject>
@ -48,6 +50,7 @@ class VisibilityManager : public QObject
Q_PROPERTY(bool enabledDynamicBackground READ enabledDynamicBackground WRITE setEnabledDynamicBackground NOTIFY enabledDynamicBackgroundChanged)
Q_PROPERTY(bool existsWindowMaximized READ existsWindowMaximized NOTIFY existsWindowMaximizedChanged)
Q_PROPERTY(bool existsWindowSnapped READ existsWindowSnapped NOTIFY existsWindowSnappedChanged)
Q_PROPERTY(SchemeColors *touchingWindowScheme READ touchingWindowScheme NOTIFY touchingWindowSchemeChanged)
//! KWin Edges Support Options
Q_PROPERTY(bool enableKWinEdges READ enableKWinEdges WRITE setEnableKWinEdges NOTIFY enableKWinEdgesChanged)
@ -93,6 +96,8 @@ public:
bool existsWindowMaximized() const;
bool existsWindowSnapped() const;
SchemeColors *touchingWindowScheme() const;
//! KWin Edges Support functions
bool enableKWinEdges() const;
void setEnableKWinEdges(bool enable);
@ -111,6 +116,7 @@ signals:
void containsMouseChanged();
void timerShowChanged();
void timerHideChanged();
void touchingWindowSchemeChanged();
//! Dynamic Background signals (from options)
void enabledDynamicBackgroundChanged();

@ -1,8 +1,9 @@
#ifndef VISIBILITYMANAGERPRIVATE_H
#define VISIBILITYMANAGERPRIVATE_H
#include "../windowinfowrap.h"
#include "../abstractwindowinterface.h"
#include "../schemecolors.h"
#include "../windowinfowrap.h"
#include "../../liblattedock/dock.h"
#include <array>
@ -55,6 +56,7 @@ public:
void setEnabledDynamicBackground(bool active);
void setExistsWindowMaximized(bool windowMaximized);
void setExistsWindowSnapped(bool windowSnapped);
void setTouchingWindowScheme(SchemeColors *scheme);
void updateAvailableScreenGeometry();
void updateDynamicBackgroundWindowFlags();
@ -112,6 +114,8 @@ public:
QList<QRect> snappedWindowsGeometries;
std::array<QMetaObject::Connection, 7> connectionsDynBackground;
WindowId lastActiveWindowWid;
SchemeColors *touchingScheme{nullptr};
//! KWin Edges
bool enableKWinEdgesFromUser{true};

@ -866,6 +866,15 @@ void DockCorona::activateLauncherMenu()
m_globalShortcuts->activateLauncherMenu();
}
void DockCorona::windowColorScheme(QString windowIdAndScheme)
{
int firstSlash = windowIdAndScheme.indexOf("-");
QString windowIdStr = windowIdAndScheme.mid(0,firstSlash);
QString schemeStr = windowIdAndScheme.mid(firstSlash+1);
m_wm->setColorSchemeForWindow(windowIdStr, schemeStr);
}
//! update badge for specific dock item
void DockCorona::updateDockItemBadge(QString identifier, QString value)
{

@ -113,6 +113,8 @@ public:
public slots:
void aboutApplication();
void activateLauncherMenu();
//! they are separated with a "-" character
void windowColorScheme(QString windowIdAndScheme);
void loadDefaultLayout() override;
void updateDockItemBadge(QString identifier, QString value);
void unload();

@ -0,0 +1,137 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "schemecolors.h"
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <KConfigGroup>
#include <KSharedConfig>
namespace Latte {
SchemeColors::SchemeColors(QObject *parent, QString scheme) :
QObject(parent)
{
QString pSchemeFile = possibleSchemeFile(scheme);
if (QFileInfo(pSchemeFile).exists()) {
m_schemeFile = pSchemeFile;
m_schemeName = scheme;
}
updateScheme();
}
SchemeColors::~SchemeColors()
{
///
}
QColor SchemeColors::backgroundColor() const
{
return subgroup() == Active ? m_activeBackgroundColor : m_inactiveBackgroundColor;
}
QColor SchemeColors::foregroundColor() const
{
return subgroup() == Active ? m_activeForegroundColor : m_inactiveForegroundColor;
}
QString SchemeColors::schemeName()
{
return m_schemeName;
}
QString SchemeColors::schemeFile()
{
return m_schemeFile;
}
SchemeColors::ColorsSubgroup SchemeColors::subgroup() const
{
return m_subgroup;
}
void SchemeColors::setSubgroup(ColorsSubgroup subgroup)
{
if (m_subgroup == subgroup) {
return;
}
m_subgroup = subgroup;
emit colorsChanged();
}
QString SchemeColors::possibleSchemeFile(QString scheme)
{
if (scheme.startsWith("/") && scheme.endsWith(".colors") && QFileInfo(scheme).exists()) {
return scheme;
}
QString tempScheme = scheme;
if (scheme == "kdeglobals") {
QString settingsFile = QDir::homePath() + "/.config/kdeglobals";
if (QFileInfo(settingsFile).exists()) {
KSharedConfigPtr filePtr = KSharedConfig::openConfig(settingsFile);
KConfigGroup generalGroup = KConfigGroup(filePtr, "General");
tempScheme = generalGroup.readEntry("ColorScheme", "");
}
}
//! remove all whitespaces and "-" from scheme in order to access correctly its file
QString schemeNameSimplified = tempScheme.simplified().remove(" ").remove("-");
QString localSchemePath = QDir::homePath() + "/.local/share/color-schemes/" + schemeNameSimplified + ".colors";
QString globalSchemePath = "/usr/share/color-schemes/" + schemeNameSimplified + ".colors";
if (QFileInfo(localSchemePath).exists()) {
return localSchemePath;
} else if (QFileInfo(globalSchemePath).exists()) {
return globalSchemePath;
}
return "";
}
void SchemeColors::updateScheme()
{
if (m_schemeFile.isEmpty() || !QFileInfo(m_schemeFile).exists()) {
return;
}
KSharedConfigPtr filePtr = KSharedConfig::openConfig(m_schemeFile);
KConfigGroup wmGroup = KConfigGroup(filePtr, "WM");
m_activeBackgroundColor = wmGroup.readEntry("activeBackground", QColor());
m_activeForegroundColor = wmGroup.readEntry("activeForeground", QColor());
m_inactiveBackgroundColor = wmGroup.readEntry("inactiveBackground", QColor());
m_inactiveForegroundColor = wmGroup.readEntry("inactiveForeground", QColor());
emit colorsChanged();
}
}

@ -0,0 +1,78 @@
/*
* Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef SCHEMECOLORS_H
#define SCHEMECOLORS_H
#include <QObject>
#include <QColor>
namespace Latte {
class SchemeColors: public QObject
{
Q_OBJECT
Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY colorsChanged)
Q_PROPERTY(QColor foregroundColor READ foregroundColor NOTIFY colorsChanged)
public:
enum ColorsSubgroup
{
Active = 0,
Inactive = 1
};
Q_ENUM(ColorsSubgroup);
SchemeColors(QObject *parent, QString scheme);
~SchemeColors() override;
QString schemeName();
QString schemeFile();
QColor backgroundColor() const;
QColor foregroundColor() const;
SchemeColors::ColorsSubgroup subgroup() const;
void setSubgroup(SchemeColors::ColorsSubgroup subgroup);
static QString possibleSchemeFile(QString scheme);
signals:
void colorsChanged();
private slots:
void updateScheme();
private:
QString m_schemeName;
QString m_schemeFile;
QColor m_activeBackgroundColor;
QColor m_activeForegroundColor;
QColor m_inactiveBackgroundColor;
QColor m_inactiveForegroundColor;
ColorsSubgroup m_subgroup{SchemeColors::Active};
};
}
#endif

@ -473,6 +473,15 @@ Item{
}
}
Rectangle {
anchors.fill: solidBackground
opacity: showColoredPanel ? solidBackground.opacity : 0
color: showColoredPanel ? dock.visibility.touchingWindowScheme.backgroundColor : "#00000000"
readonly property bool showColoredPanel: dock && dock.visibility && (dock.visibility.existsWindowMaximized || dock.visibility.existsWindowSnapped)
&& !hasExpandedApplet
}
PlasmaCore.FrameSvgItem{
id: hiddenPanelBackground
imagePath: "widgets/panel-background"

@ -1736,10 +1736,17 @@ DragDrop.DropArea {
Loader{
id: colorizerLoader
active: forceColorizer
active: forceColorizer || forceSolidnessAndColorize
anchors.fill: layoutsContainer
z: layoutsContainer.z + 1
readonly property bool forceSolidness: (root.solidPanel && !plasmoid.configuration.solidBackgroundForMaximized) || root.forceSolidPanel
|| !Latte.WindowSystem.compositingActive
readonly property bool forceSolidnessAndColorize: forceSolidness && dock && dock.visibility
&& (dock.visibility.existsWindowMaximized || dock.visibility.existsWindowSnapped)
&& !root.hasExpandedApplet
// formula for luminance according to:
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
property real textColorRs: {
@ -1801,7 +1808,7 @@ DragDrop.DropArea {
readonly property real themeTextColorLuma: 0.2126*textColorRs + 0.7152*textColorGs + 0.0722*textColorBs
readonly property color minimizedDotColor: themeTextColorLuma > 0.6 ? Qt.darker(theme.textColor, 1.7) : Qt.lighter(theme.textColor, 7)
property bool isShown: active && !forceSolidPanel
property bool isShown: active && (!forceSolidPanel || forceSolidnessAndColorize)
//! when forceSemiTransparentPanel is enabled because of snapped or maximized etc. windows
//! then the colorizer could be enabled for low panel transparency levels (<40%)
&& (!userShowPanelBackground || !forceSemiTransparentPanel || (forceSemiTransparentPanel && root.panelTransparency<40))
@ -1815,6 +1822,10 @@ DragDrop.DropArea {
property color themeDarkColor: themeBackgroundColorLuma > themeTextColorLuma ? theme.textColor : theme.backgroundColor
property color applyColor: {
if (forceSolidnessAndColorize && dock.visibility.touchingWindowScheme) {
return dock.visibility.touchingWindowScheme.foregroundColor;
}
if (currentBackgroundLuminas>=0) {
var textAbs = Math.abs(themeTextColorLuma - currentBackgroundLuminas);
var backAbs = Math.abs(themeBackgroundColorLuma - currentBackgroundLuminas);

Loading…
Cancel
Save