diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,9 @@ find_package(KF5Config REQUIRED) find_package(KF5IconThemes REQUIRED) find_package(KF5DBusAddons REQUIRED) +find_package(KF5Service REQUIRED) find_package(PkgConfig REQUIRED) +find_package(KDecoration2 REQUIRED) find_package(GSettingSchemas REQUIRED) find_package(XSettingsd) diff --git a/kded/CMakeLists.txt b/kded/CMakeLists.txt --- a/kded/CMakeLists.txt +++ b/kded/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(kwin_bridge) + set(kscreen_daemon_SRCS gtkconfig.cpp configeditor.cpp @@ -14,11 +16,13 @@ target_include_directories(gtkconfig PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} ${GTK3_INCLUDE_DIRS} ) target_link_libraries(gtkconfig + PRIVATE + KWinBridge + PUBLIC Qt5::DBus KF5::CoreAddons KF5::ConfigCore diff --git a/kded/configvalueprovider.h b/kded/configvalueprovider.h --- a/kded/configvalueprovider.h +++ b/kded/configvalueprovider.h @@ -20,6 +20,8 @@ #pragma once +#include + #include class QString; @@ -39,11 +41,13 @@ bool scrollbarBehavior() const; bool preferDarkTheme() const; QString windowDecorationsButtonsOrder() const; + QVariantMap windowDecorationsButtonsImages() const; bool enableAnimations() const; private: QString fontStyleHelper(const QFont &font) const; QString windowDecorationButtonsOrderInGtkNotation(const QString &kdeConfigValue) const; + QString currentWindowDecorationPluginPath() const; KSharedConfigPtr kdeglobalsConfig; KSharedConfigPtr inputConfig; diff --git a/kded/configvalueprovider.cpp b/kded/configvalueprovider.cpp --- a/kded/configvalueprovider.cpp +++ b/kded/configvalueprovider.cpp @@ -21,14 +21,26 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include + +#include "dummydecorationbridge.h" #include "configvalueprovider.h" ConfigValueProvider::ConfigValueProvider() : @@ -170,6 +182,52 @@ return windowBackgroundGray < 192; } +QVariantMap ConfigValueProvider::windowDecorationsButtonsImages() const +{ + const QString decorationPluginPath = currentWindowDecorationPluginPath(); + + KPluginLoader loader {decorationPluginPath}; + qDebug() << "Loader:" << loader.fileName(); + KPluginFactory *factory = loader.factory(); + qDebug() << "Factory:" << factory; + + std::unique_ptr bridge {new KDecoration2::DummyDecorationBridge()}; + QVariantMap args({ {QStringLiteral("bridge"), QVariant::fromValue(bridge.get())} }); + qDebug() << "Args:" << args; + auto currentDecoration = factory->create(factory, QVariantList({args})); + qDebug() << "currentDecoration:" << currentDecoration; + auto btn = QVariant::fromValue(KDecoration2::DecorationButtonType::Close); + qDebug() << "Btn:" << btn; + auto dec = QVariant::fromValue(currentDecoration); + qDebug() << "Dec:" << btn; + auto closeButton = factory->create(QStringLiteral("button"), currentDecoration, QVariantList({btn, dec})); + qDebug() << "Close btn:" << currentDecoration; + + if (closeButton == nullptr) { + qDebug() << "close btn is null!"; + return {}; + } + + qDebug() << "Creating pixmap..."; + QPixmap pixmap {30, 30}; + QPainter painter {&pixmap}; + + qDebug() << "Painting decoration..."; + closeButton->paint(&painter, {0, 0, 30, 30}); + qDebug() << "Saving qpainter..."; + painter.save(); + + qDebug() << "Saving to file..."; + QFile file {QDir::homePath() + "test_close.png"}; + file.open(QIODevice::ReadWrite | QIODevice::Truncate); + pixmap.save(&file, "PNG"); + file.close(); + + qDebug() << "SAVED!"; + + return {}; +} + QString ConfigValueProvider::windowDecorationsButtonsOrder() const { KConfigGroup configGroup = kwinConfig->group(QStringLiteral("org.kde.kdecoration2")); @@ -209,3 +267,22 @@ return gtkNotation; } + +QString ConfigValueProvider::currentWindowDecorationPluginPath() const +{ + KConfigGroup decorationGroup = kwinConfig->group(QStringLiteral("org.kde.kdecoration2")); + const QString themeName = decorationGroup.readEntry(QStringLiteral("theme"), QStringLiteral("Breeze")); + + const auto decorationPlugins = KPluginLoader::findPlugins(QStringLiteral("org.kde.kdecoration2")); + QString defaultPluginPath; + + for (const auto &plugin : decorationPlugins) { + if (plugin.name() == themeName) { + return plugin.fileName(); + } + if (plugin.name() == QStringLiteral("Breeze")) { + defaultPluginPath = plugin.fileName(); + } + } + return defaultPluginPath; +} diff --git a/kded/gtkconfig.h b/kded/gtkconfig.h --- a/kded/gtkconfig.h +++ b/kded/gtkconfig.h @@ -45,6 +45,7 @@ void setToolbarStyle() const; void setScrollbarBehavior() const; void setDarkThemePreference() const; + void setWindowDecorationsAppearance() const; void setWindowDecorationsButtonsOrder() const; void setEnableAnimations() const; diff --git a/kded/gtkconfig.cpp b/kded/gtkconfig.cpp --- a/kded/gtkconfig.cpp +++ b/kded/gtkconfig.cpp @@ -159,6 +159,12 @@ ConfigEditor::setGtk3ConfigValueSettingsIni(QStringLiteral("gtk-application-prefer-dark-theme"), preferDarkTheme); } +void GtkConfig::setWindowDecorationsAppearance() const +{ + const auto windowDecorationsButtonsImages = configValueProvider->windowDecorationsButtonsImages(); + // TODO: Save images to where it's needed +} + void GtkConfig::setWindowDecorationsButtonsOrder() const { const QString windowDecorationsButtonOrder = configValueProvider->windowDecorationsButtonsOrder(); @@ -186,6 +192,7 @@ setToolbarStyle(); setScrollbarBehavior(); setDarkThemePreference(); + setWindowDecorationsAppearance(); setWindowDecorationsButtonsOrder(); setEnableAnimations(); } @@ -225,9 +232,14 @@ void GtkConfig::onKWinSettingsChange(const KConfigGroup &group, const QByteArrayList &names) const { - if (group.name() == QStringLiteral("org.kde.kdecoration2") - && (names.contains("ButtonsOnRight") || names.contains("ButtonsOnLeft"))) { - setWindowDecorationsButtonsOrder(); + if (group.name() == QStringLiteral("org.kde.kdecoration2")) { + if (names.contains(QByteArrayLiteral("ButtonsOnRight")) + || names.contains(QByteArrayLiteral("ButtonsOnLeft"))) { + setWindowDecorationsButtonsOrder(); + } + if (names.contains(QByteArrayLiteral("theme"))) { + setWindowDecorationsAppearance(); + } } } diff --git a/kded/kwin_bridge/CMakeLists.txt b/kded/kwin_bridge/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kded/kwin_bridge/CMakeLists.txt @@ -0,0 +1,13 @@ +add_library(KWinBridge STATIC + dummydecoratedclient.cpp + dummydecorationbridge.cpp +) + +target_link_libraries(KWinBridge + PUBLIC + KDecoration2::KDecoration + KDecoration2::KDecoration2Private + Qt5::DBus + KF5::CoreAddons + KF5::Service +) diff --git a/kded/kwin_bridge/dummydecoratedclient.h b/kded/kwin_bridge/dummydecoratedclient.h new file mode 100644 --- /dev/null +++ b/kded/kwin_bridge/dummydecoratedclient.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2020 Mikhail Zolotukhin + * + * This program 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 . + */ + +#pragma once + +#include + +#include +#include + +namespace KDecoration2 { + +class DummyDecoratedClient : public QObject, public DecoratedClientPrivate { + Q_OBJECT +public: + DummyDecoratedClient(DecoratedClient *client, Decoration *decoration); + + bool isActive() const override; + QString caption() const override; + int desktop() const override; + bool isOnAllDesktops() const override; + bool isShaded() const override; + QIcon icon() const override; + bool isMaximized() const override; + bool isMaximizedHorizontally() const override; + bool isMaximizedVertically() const override; + bool isKeepAbove() const override; + bool isKeepBelow() const override; + + bool isCloseable() const override; + bool isMaximizeable() const override; + bool isMinimizeable() const override; + bool providesContextHelp() const override; + bool isModal() const override; + bool isShadeable() const override; + bool isMoveable() const override; + bool isResizeable() const override; + + WId windowId() const override; + WId decorationId() const override; + + int width() const override; + int height() const override; + QSize size() const override; + QPalette palette() const override; + Qt::Edges adjacentScreenEdges() const override; + + void requestShowToolTip(const QString &text) override; + + void requestHideToolTip() override; + void requestClose() override; + void requestToggleMaximization(Qt::MouseButtons buttons) override; + void requestMinimize() override; + void requestContextHelp() override; + void requestToggleOnAllDesktops() override; + void requestToggleShade() override; + void requestToggleKeepAbove() override; + void requestToggleKeepBelow() override; + void requestShowWindowMenu() override; +}; + +} diff --git a/kded/kwin_bridge/dummydecoratedclient.cpp b/kded/kwin_bridge/dummydecoratedclient.cpp new file mode 100644 --- /dev/null +++ b/kded/kwin_bridge/dummydecoratedclient.cpp @@ -0,0 +1,172 @@ +/* + * Copyright 2020 Mikhail Zolotukhin + * + * This program 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 . + */ + +#include "dummydecoratedclient.h" + +namespace KDecoration2 { + +DummyDecoratedClient::DummyDecoratedClient(DecoratedClient *client, Decoration *decoration) + : DecoratedClientPrivate(client, decoration) +{ + qDebug() << "Dummy client constructor is called!"; +} + +bool DummyDecoratedClient::isActive() const +{ + return true; +} + +QString DummyDecoratedClient::caption() const +{ + return {}; +} + +int DummyDecoratedClient::desktop() const +{ + return 0; +} +bool DummyDecoratedClient::isOnAllDesktops() const +{ + return true; +} +bool DummyDecoratedClient::isShaded() const +{ + return true; +} +QIcon DummyDecoratedClient::icon() const +{ + return {}; +} +bool DummyDecoratedClient::isMaximized() const +{ + return true; +} +bool DummyDecoratedClient::isMaximizedHorizontally() const +{ + return true; +} +bool DummyDecoratedClient::isMaximizedVertically() const +{ + return true; +} +bool DummyDecoratedClient::isKeepAbove() const +{ + return true; +} +bool DummyDecoratedClient::isKeepBelow() const +{ + return true; +} +bool DummyDecoratedClient::isCloseable() const +{ + return true; +} +bool DummyDecoratedClient::isMaximizeable() const +{ + return true; +} +bool DummyDecoratedClient::isMinimizeable() const +{ + return true; +} +bool DummyDecoratedClient::providesContextHelp() const +{ + return true; +} +bool DummyDecoratedClient::isModal() const +{ + return true; +} +bool DummyDecoratedClient::isShadeable() const +{ + return true; +} +bool DummyDecoratedClient::isMoveable() const +{ + return true; +} +bool DummyDecoratedClient::isResizeable() const +{ + return true; +} +WId DummyDecoratedClient::windowId() const +{ + return {}; +} +WId DummyDecoratedClient::decorationId() const +{ + return {}; +} +int DummyDecoratedClient::width() const +{ + return {}; +} +int DummyDecoratedClient::height() const +{ + return {}; +} +QSize DummyDecoratedClient::size() const +{ + return {}; +} +QPalette DummyDecoratedClient::palette() const +{ + return {}; +} +Qt::Edges DummyDecoratedClient::adjacentScreenEdges() const +{ + return {}; +} +void DummyDecoratedClient::requestShowToolTip(const QString &text) +{ + Q_UNUSED(text) +} +void DummyDecoratedClient::requestHideToolTip() +{ } +void DummyDecoratedClient::requestClose() +{ +} +void DummyDecoratedClient::requestToggleMaximization(Qt::MouseButtons buttons) +{ + Q_UNUSED(buttons) +} +void DummyDecoratedClient::requestMinimize() +{ +} +void DummyDecoratedClient::requestContextHelp() +{ +} +void DummyDecoratedClient::requestToggleOnAllDesktops() +{ +} +void DummyDecoratedClient::requestToggleShade() +{ +} +void DummyDecoratedClient::requestToggleKeepAbove() +{ +} +void DummyDecoratedClient::requestToggleKeepBelow() +{ +} +void DummyDecoratedClient::requestShowWindowMenu() +{ +} + +} diff --git a/kded/configvalueprovider.h b/kded/kwin_bridge/dummydecorationbridge.h copy from kded/configvalueprovider.h copy to kded/kwin_bridge/dummydecorationbridge.h --- a/kded/configvalueprovider.h +++ b/kded/kwin_bridge/dummydecorationbridge.h @@ -1,51 +1,47 @@ /* - * Copyright (C) 2019 Mikhail Zolotukhin - * + * Copyright 2020 Mikhail Zolotukhin + * * This program 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) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. - * + * * This program 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 . */ #pragma once -#include +#include +#include -class QString; -class QFont; +namespace KDecoration2 +{ + +class DecorationSettings; +class DecoratedClientPrivate; +class DecorationSettingsPrivate; -class ConfigValueProvider +class DummyDecorationBridge : public DecorationBridge { + Q_OBJECT public: - ConfigValueProvider(); - - QString fontName() const; - QString iconThemeName() const; - QString cursorThemeName() const; - bool iconsOnButtons() const; - bool iconsInMenus() const; - int toolbarStyle() const; - bool scrollbarBehavior() const; - bool preferDarkTheme() const; - QString windowDecorationsButtonsOrder() const; - bool enableAnimations() const; - -private: - QString fontStyleHelper(const QFont &font) const; - QString windowDecorationButtonsOrderInGtkNotation(const QString &kdeConfigValue) const; - - KSharedConfigPtr kdeglobalsConfig; - KSharedConfigPtr inputConfig; - KSharedConfigPtr kwinConfig; + explicit DummyDecorationBridge(QObject* parent = nullptr); + ~DummyDecorationBridge() override = default; + + std::unique_ptr settings(KDecoration2::DecorationSettings* parent) override; + void update(KDecoration2::Decoration* decoration, const QRect& geometry) override; + std::unique_ptr createClient(KDecoration2::DecoratedClient* client, KDecoration2::Decoration* decoration) override; }; + +} + + diff --git a/kded/kwin_bridge/dummydecorationbridge.cpp b/kded/kwin_bridge/dummydecorationbridge.cpp new file mode 100644 --- /dev/null +++ b/kded/kwin_bridge/dummydecorationbridge.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2020 Mikhail Zolotukhin + * + * This program 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) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program 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 . + */ + +#include +#include +#include +#include +#include + +#include + +#include "dummydecorationbridge.h" +#include "dummydecoratedclient.h" + +namespace KDecoration2 +{ + +DummyDecorationBridge::DummyDecorationBridge(QObject* parent) +: DecorationBridge(parent) +{ + +} + +std::unique_ptr< KDecoration2::DecorationSettingsPrivate > DummyDecorationBridge::settings(KDecoration2::DecorationSettings* parent) +{ + Q_UNUSED(parent) + qDebug() << "Dummy settings method called!"; + return nullptr; +} + +void DummyDecorationBridge::update(KDecoration2::Decoration* decoration, const QRect& geometry) +{ + Q_UNUSED(decoration) + Q_UNUSED(geometry) + qDebug() << "Dummy update method called!"; +} + +std::unique_ptr< KDecoration2::DecoratedClientPrivate > DummyDecorationBridge::createClient(KDecoration2::DecoratedClient* client, KDecoration2::Decoration* decoration) +{ + qDebug() << "Dummy createClient method called!"; + return std::unique_ptr(new DummyDecoratedClient(client, decoration)); +} + +};