diff --git a/clients/aurorae/src/CMakeLists.txt b/clients/aurorae/src/CMakeLists.txt index 830ecb7e0b..f1306f9757 100644 --- a/clients/aurorae/src/CMakeLists.txt +++ b/clients/aurorae/src/CMakeLists.txt @@ -5,26 +5,23 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -set(kwin3_aurorae_PART_SRCS +set(kwin5_aurorae_PART_SRCS aurorae.cpp decorationoptions.cpp lib/auroraetheme.cpp lib/themeconfig.cpp ) -add_library(kwin3_aurorae MODULE ${kwin3_aurorae_PART_SRCS}) +add_library(kwin5_aurorae MODULE ${kwin5_aurorae_PART_SRCS}) -target_link_libraries(kwin3_aurorae - KF5::ConfigCore +target_link_libraries(kwin5_aurorae + KDecoration2::KDecoration KF5::Service + KF5::WindowSystem Qt5::Quick - Qt5::Widgets - kdecorations ) -kservice_desktop_to_json(kwin3_aurorae aurorae.desktop) - -install(TARGETS kwin3_aurorae DESTINATION ${PLUGIN_INSTALL_DIR}/kwin/kdecorations ) +install(TARGETS kwin5_aurorae DESTINATION ${PLUGIN_INSTALL_DIR}/org.kde.kdecoration2) set(decoration_plugin_SRCS decorationplugin.cpp @@ -35,9 +32,8 @@ set(decoration_plugin_SRCS add_library(decorationplugin SHARED ${decoration_plugin_SRCS}) target_link_libraries(decorationplugin Qt5::Quick - kdecorations + KDecoration2::KDecoration KF5::ConfigWidgets - KF5::Plasma ) install(TARGETS decorationplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/kwin/decoration) diff --git a/clients/aurorae/src/aurorae.cpp b/clients/aurorae/src/aurorae.cpp index 26b44a957f..e74a6e42fb 100644 --- a/clients/aurorae/src/aurorae.cpp +++ b/clients/aurorae/src/aurorae.cpp @@ -20,54 +20,161 @@ along with this program. If not, see . #include "config-kwin.h" // qml imports #include "decorationoptions.h" - -#include +// KDecoration2 +#include +#include +// KDE +#include +#include +#include +#include +#include +// Qt #include #include -#include -#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include - -K_PLUGIN_FACTORY_WITH_JSON(AuroraePluginFactory, +K_PLUGIN_FACTORY_WITH_JSON(AuroraeDecoFactory, "aurorae.json", - registerPlugin(QString(), &Aurorae::AuroraeFactory::createInstance);) -K_EXPORT_PLUGIN_VERSION(KWIN_DECORATION_API_VERSION) + registerPlugin();) namespace Aurorae { -AuroraeFactory::AuroraeFactory(QObject *parent) - : KDecorationFactory(parent) - , m_theme(new AuroraeTheme(this)) - , m_engine(new QQmlEngine(this)) - , m_component(new QQmlComponent(m_engine, this)) - , m_engineType(AuroraeEngine) - , m_mutex(new QMutex(QMutex::Recursive)) +class Helper { - init(); - connect(options(), &KDecorationOptions::buttonsChanged, this, &AuroraeFactory::buttonsChanged); - connect(options(), &KDecorationOptions::fontsChanged, this, &AuroraeFactory::titleFontChanged); - connect(options(), &KDecorationOptions::configChanged, this, &AuroraeFactory::updateConfiguration); +public: + void ref(); + void unref(); + QQmlComponent *component(const QString &theme); + QQmlContext *rootContext(); + QQmlComponent *svgComponent() { + return m_svgComponent.data(); + } + + static Helper &instance(); +private: + Helper() = default; + void init(); + QQmlComponent *loadComponent(const QString &themeName); + int m_refCount = 0; + QScopedPointer m_engine; + QHash m_components; + QScopedPointer m_svgComponent; +}; + +Helper &Helper::instance() +{ + static Helper s_helper; + return s_helper; } -void AuroraeFactory::init() +void Helper::ref() { - qRegisterMetaType("Qt::MouseButtons"); + m_refCount++; + if (m_refCount == 1) { + m_engine.reset(new QQmlEngine); + init(); + } +} +void Helper::unref() +{ + m_refCount--; + if (m_refCount == 0) { + // cleanup + m_svgComponent.reset(); + m_engine.reset(); + m_components.clear(); + } +} + +static const QString s_defaultTheme = QStringLiteral("kwin4_decoration_qml_plastik"); + +QQmlComponent *Helper::component(const QString &themeName) +{ + // maybe it's an SVG theme? + if (themeName.startsWith(QLatin1Literal("__aurorae__svg__"))) { + if (m_svgComponent.isNull()) { + /* use logic from KDeclarative::setupBindings(): + "addImportPath adds the path at the beginning, so to honour user's + paths we need to traverse the list in reverse order" */ + QStringListIterator paths(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("module/imports"), QStandardPaths::LocateDirectory)); + paths.toBack(); + while (paths.hasPrevious()) { + m_engine->addImportPath(paths.previous()); + } + m_svgComponent.reset(new QQmlComponent(m_engine.data())); + m_svgComponent->loadUrl(QUrl(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/aurorae/aurorae.qml")))); + } + return m_svgComponent.data(); + } + // try finding the QML package + auto it = m_components.constFind(themeName); + if (it != m_components.constEnd()) { + return it.value(); + } + auto component = loadComponent(themeName); + if (component) { + m_components.insert(themeName, component); + return component; + } + // try loading default component + if (themeName != s_defaultTheme) { + return loadComponent(s_defaultTheme); + } + return nullptr; +} + +QQmlComponent *Helper::loadComponent(const QString &themeName) +{ + qCDebug(AURORAE) << "Trying to load QML Decoration " << themeName; + const QString internalname = themeName.toLower(); + + QString constraint = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(internalname); + KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("KWin/Decoration"), constraint); + if (offers.isEmpty()) { + qCCritical(AURORAE) << "Couldn't find QML Decoration " << themeName << endl; + // TODO: what to do in error case? + return nullptr; + } + KService::Ptr service = offers.first(); + const QString pluginName = service->property(QStringLiteral("X-KDE-PluginInfo-Name")).toString(); + const QString scriptName = service->property(QStringLiteral("X-Plasma-MainScript")).toString(); + const QString file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral(KWIN_NAME) + QStringLiteral("/decorations/") + pluginName + QStringLiteral("/contents/") + scriptName); + if (file.isNull()) { + qCDebug(AURORAE) << "Could not find script file for " << pluginName; + // TODO: what to do in error case? + return nullptr; + } + // setup the QML engine + /* use logic from KDeclarative::setupBindings(): + "addImportPath adds the path at the beginning, so to honour user's + paths we need to traverse the list in reverse order" */ + QStringListIterator paths(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("module/imports"), QStandardPaths::LocateDirectory)); + paths.toBack(); + while (paths.hasPrevious()) { + m_engine->addImportPath(paths.previous()); + } + QQmlComponent *component = new QQmlComponent(m_engine.data(), m_engine.data()); + component->loadUrl(QUrl::fromLocalFile(file)); + return component; +} + +QQmlContext *Helper::rootContext() +{ + return m_engine->rootContext(); +} + +void Helper::init() +{ // we need to first load our decoration plugin // once it's loaded we can provide the Borders and access them from C++ side // so let's try to locate our plugin: @@ -95,224 +202,80 @@ void AuroraeFactory::init() m_engine->importPlugin(pluginPath, "org.kde.kwin.decoration", nullptr); qmlRegisterType("org.kde.kwin.decoration", 0, 1, "Borders"); - KConfig conf(QStringLiteral("auroraerc")); - KConfigGroup group(&conf, "Engine"); - if (!group.hasKey("EngineType") && !group.hasKey("ThemeName")) { - // neither engine type and theme name are configured, use the only available theme - initQML(group); - } else if (group.hasKey("EngineType")) { - const QString engineType = group.readEntry("EngineType", "aurorae").toLower(); - if (engineType == QStringLiteral("qml")) { - initQML(group); - } else { - // fallback to classic Aurorae Themes - initAurorae(conf, group); - } - } else { - // fallback to classic Aurorae Themes - initAurorae(conf, group); - } + qmlRegisterType(); + qmlRegisterType(); } -void AuroraeFactory::initAurorae(KConfig &conf, KConfigGroup &group) -{ - m_engineType = AuroraeEngine; - const QString themeName = group.readEntry("ThemeName"); - if (themeName.isEmpty()) { - // no theme configured, fall back to Plastik QML theme - initQML(group); - return; - } - KConfig config(QStringLiteral("aurorae/themes/") + themeName + QStringLiteral("/") + themeName + QStringLiteral("rc"), - KConfig::FullConfig, QStandardPaths::GenericDataLocation); - KConfigGroup themeGroup(&conf, themeName); - m_theme->loadTheme(themeName, config); - m_theme->setBorderSize((KDecorationDefines::BorderSize)themeGroup.readEntry("BorderSize", KDecorationDefines::BorderNormal)); - m_theme->setButtonSize((KDecorationDefines::BorderSize)themeGroup.readEntry("ButtonSize", KDecorationDefines::BorderNormal)); - m_theme->setTabDragMimeType(tabDragMimeType()); - // setup the QML engine - /* use logic from KDeclarative::setupBindings(): - "addImportPath adds the path at the beginning, so to honour user's - paths we need to traverse the list in reverse order" */ - QStringListIterator paths(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("module/imports"), QStandardPaths::LocateDirectory)); - paths.toBack(); - while (paths.hasPrevious()) { - m_engine->addImportPath(paths.previous()); - } - m_component->loadUrl(QUrl(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/aurorae/aurorae.qml")))); - m_engine->rootContext()->setContextProperty(QStringLiteral("auroraeTheme"), m_theme); - m_themeName = themeName; -} -void AuroraeFactory::initQML(const KConfigGroup &group) -{ - // try finding the QML package - const QString themeName = group.readEntry("ThemeName", "kwin4_decoration_qml_plastik"); - qCDebug(AURORAE) << "Trying to load QML Decoration " << themeName; - const QString internalname = themeName.toLower(); - - QString constraint = QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(internalname); - KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("KWin/Decoration"), constraint); - if (offers.isEmpty()) { - qCCritical(AURORAE) << "Couldn't find QML Decoration " << themeName << endl; - // TODO: what to do in error case? - return; - } - KService::Ptr service = offers.first(); - const QString pluginName = service->property(QStringLiteral("X-KDE-PluginInfo-Name")).toString(); - const QString scriptName = service->property(QStringLiteral("X-Plasma-MainScript")).toString(); - const QString file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral(KWIN_NAME) + QStringLiteral("/decorations/") + pluginName + QStringLiteral("/contents/") + scriptName); - if (file.isNull()) { - qCDebug(AURORAE) << "Could not find script file for " << pluginName; - // TODO: what to do in error case? - return; - } - m_engineType = QMLEngine; - // setup the QML engine - /* use logic from KDeclarative::setupBindings(): - "addImportPath adds the path at the beginning, so to honour user's - paths we need to traverse the list in reverse order" */ - QStringListIterator paths(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("module/imports"), QStandardPaths::LocateDirectory)); - paths.toBack(); - while (paths.hasPrevious()) { - m_engine->addImportPath(paths.previous()); - } - m_component->loadUrl(QUrl::fromLocalFile(file)); - m_themeName = themeName; -} - -AuroraeFactory::~AuroraeFactory() -{ - s_instance = nullptr; -} - -AuroraeFactory *AuroraeFactory::instance() -{ - if (!s_instance) { - s_instance = new AuroraeFactory; - } - - return s_instance; -} - -QObject *AuroraeFactory::createInstance(QWidget*, QObject*, const QList< QVariant >&) -{ - return instance(); -} - -void AuroraeFactory::updateConfiguration() -{ - const KConfig conf(QStringLiteral("auroraerc")); - const KConfigGroup group(&conf, "Engine"); - const QString themeName = group.readEntry("ThemeName", "example-deco"); - const KConfig config(QStringLiteral("aurorae/themes/") + themeName + QStringLiteral("/") + themeName + QStringLiteral("rc"), - KConfig::FullConfig, QStandardPaths::GenericDataLocation); - const KConfigGroup themeGroup(&conf, themeName); - if (themeName != m_themeName) { - m_engine->clearComponentCache(); - init(); - emit recreateDecorations(); - } - if (m_engineType == AuroraeEngine) { - m_theme->setBorderSize((KDecorationDefines::BorderSize)themeGroup.readEntry("BorderSize", KDecorationDefines::BorderNormal)); - m_theme->setButtonSize((KDecorationDefines::BorderSize)themeGroup.readEntry("ButtonSize", KDecorationDefines::BorderNormal)); - } else { - // we don't know how the settings change -> recreate - emit recreateDecorations(); - } - emit configChanged(); -} - -bool AuroraeFactory::supports(Ability ability) const -{ - switch (ability) { - case AbilityAnnounceButtons: - case AbilityUsesAlphaChannel: - case AbilityAnnounceAlphaChannel: - case AbilityButtonMenu: - case AbilityButtonSpacer: - case AbilityExtendIntoClientArea: - case AbilityButtonMinimize: - case AbilityButtonMaximize: - case AbilityButtonClose: - case AbilityButtonAboveOthers: - case AbilityButtonBelowOthers: - case AbilityButtonShade: - case AbilityButtonOnAllDesktops: - case AbilityButtonHelp: - case AbilityButtonApplicationMenu: - case AbilityProvidesShadow: - return true; // TODO: correct value from theme - case AbilityTabbing: - return false; - case AbilityUsesBlurBehind: - return true; - default: - return false; - } -} - -KDecoration *AuroraeFactory::createDecoration(KDecorationBridge *bridge) -{ - AuroraeClient *client = new AuroraeClient(bridge, this); - return client; -} - -QList< KDecorationDefines::BorderSize > AuroraeFactory::borderSizes() const -{ - return QList< BorderSize >() << BorderTiny << BorderNormal << - BorderLarge << BorderVeryLarge << BorderHuge << - BorderVeryHuge << BorderOversized; -} - -QQuickItem *AuroraeFactory::createQmlDecoration(Aurorae::AuroraeClient *client) -{ - QQmlContext *context = new QQmlContext(m_engine->rootContext(), this); - context->setContextProperty(QStringLiteral("decoration"), client); - return qobject_cast< QQuickItem* >(m_component->create(context)); -} - -AuroraeFactory *AuroraeFactory::s_instance = nullptr; - -/******************************************************* -* Client -*******************************************************/ -AuroraeClient::AuroraeClient(KDecorationBridge *bridge, KDecorationFactory *factory) - : KDecoration(bridge, factory) - , m_view(nullptr) - , m_item(AuroraeFactory::instance()->createQmlDecoration(this)) +Decoration::Decoration(QObject *parent, const QVariantList &args) + : KDecoration2::Decoration(parent) + , m_item(nullptr) , m_borders(nullptr) , m_maximizedBorders(nullptr) , m_extendedBorders(nullptr) , m_padding(nullptr) + , m_themeName(s_defaultTheme) + , m_mutex(QMutex::Recursive) { - connect(AuroraeFactory::instance(), SIGNAL(buttonsChanged()), SIGNAL(buttonsChanged())); - connect(AuroraeFactory::instance(), SIGNAL(configChanged()), SIGNAL(configChanged())); - connect(AuroraeFactory::instance(), SIGNAL(titleFontChanged()), SIGNAL(fontChanged())); - connect(m_item, SIGNAL(alphaChanged()), SLOT(slotAlphaChanged())); - connect(this, SIGNAL(appMenuAvailable()), SIGNAL(appMenuAvailableChanged())); - connect(this, SIGNAL(appMenuUnavailable()), SIGNAL(appMenuAvailableChanged())); + if (!args.isEmpty()) { + const auto map = args.first().toMap(); + auto it = map.constFind(QStringLiteral("theme")); + if (it != map.constEnd()) { + m_themeName = it.value().toString(); + } + } + Helper::instance().ref(); } -AuroraeClient::~AuroraeClient() +Decoration::~Decoration() { - QMutexLocker locker(AuroraeFactory::instance()->mutex()); + Helper::instance().unref(); } -void AuroraeClient::init() +void Decoration::init() { - m_view = new QQuickWindow(); - m_view->setFlags(initialWFlags()); - m_view->setColor(Qt::transparent); - setMainWindow(m_view); - if (compositingActive()) { - connect(m_view, &QQuickWindow::beforeRendering, [this]() { - int left, right, top, bottom; - left = right = top = bottom = 0; - padding(left, right, top, bottom); - if (m_fbo.isNull() || m_fbo->size() != QSize(width() + left + right, height() + top + bottom)) { - m_fbo.reset(new QOpenGLFramebufferObject(QSize(width() + left + right, height() + top + bottom), - QOpenGLFramebufferObject::CombinedDepthStencil)); + KDecoration2::Decoration::init(); + QQmlContext *context = new QQmlContext(Helper::instance().rootContext(), this); + context->setContextProperty(QStringLiteral("decoration"), this); + auto component = Helper::instance().component(m_themeName); + if (!component) { + return; + } + if (component == Helper::instance().svgComponent()) { + // load SVG theme + const QString themeName = m_themeName.mid(16); + KConfig config(QStringLiteral("aurorae/themes/") + themeName + QStringLiteral("/") + themeName + QStringLiteral("rc"), + KConfig::FullConfig, QStandardPaths::GenericDataLocation); +// KConfigGroup themeGroup(&conf, themeName); + AuroraeTheme *theme = new AuroraeTheme(this); + theme->loadTheme(themeName, config); +// m_theme->setBorderSize((KDecorationDefines::BorderSize)themeGroup.readEntry("BorderSize", KDecorationDefines::BorderNormal)); +// m_theme->setButtonSize((KDecorationDefines::BorderSize)themeGroup.readEntry("ButtonSize", KDecorationDefines::BorderNormal)); +// m_theme->setTabDragMimeType(tabDragMimeType()); + context->setContextProperty(QStringLiteral("auroraeTheme"), theme); + } + m_item = qobject_cast< QQuickItem* >(component->create(context)); + if (!m_item) { + return; + } + m_item->setParent(this); + + QVariant visualParent = property("visualParent"); + if (visualParent.isValid()) { + m_item->setParentItem(visualParent.value()); + } else { + // we need a QQuickWindow till we depend on Qt 5.4 + m_decorationWindow.reset(QWindow::fromWinId(client()->decorationId())); + m_view.reset(new QQuickWindow(m_decorationWindow.data())); + m_view->setFlags(Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput); + m_view->setColor(Qt::transparent); + connect(m_view.data(), &QQuickWindow::beforeRendering, [this]() { + if (!KDecoration2::DecorationSettings::self()->isAlphaChannelSupported()) { + // directly render to QQuickWindow + return; + } + if (m_fbo.isNull() || m_fbo->size() != size()) { + m_fbo.reset(new QOpenGLFramebufferObject(size(), QOpenGLFramebufferObject::CombinedDepthStencil)); if (!m_fbo->isValid()) { qCWarning(AURORAE) << "Creating FBO as render target failed"; m_fbo.reset(); @@ -321,315 +284,150 @@ void AuroraeClient::init() } m_view->setRenderTarget(m_fbo.data()); }); - connect(m_view, &QQuickWindow::afterRendering, [this]{ - QMutexLocker locker(AuroraeFactory::instance()->mutex()); + connect(m_view.data(), &QQuickWindow::afterRendering, [this] { + if (!m_fbo) { + return; + } + QMutexLocker locker(&m_mutex); m_buffer = m_fbo->toImage(); }); - connect(m_view, &QQuickWindow::afterRendering, this, - static_cast(&KDecoration::update), Qt::QueuedConnection); - } - if (m_item) { + connect(KDecoration2::DecorationSettings::self(), &KDecoration2::DecorationSettings::alphaChannelSupportedChanged, + m_view.data(), &QQuickWindow::update); + connect(m_view.data(), &QQuickWindow::afterRendering, this, [this] { update(); }, Qt::QueuedConnection); m_item->setParentItem(m_view->contentItem()); - m_item->setParent(m_view); - setupBorders(); } - slotAlphaChanged(); - - AuroraeFactory::instance()->theme()->setCompositingActive(compositingActive()); -} - -bool AuroraeClient::eventFilter(QObject *object, QEvent *event) -{ - // we need to filter the wheel events on the decoration - // QML does not yet provide a way to accept wheel events, this will change with Qt 5 - // TODO: remove in KDE5 - // see BUG: 304248 - if (object != widget() || event->type() != QEvent::Wheel) { - return KDecoration::eventFilter(object, event); + setupBorders(m_item); + if (m_extendedBorders) { + auto updateExtendedBorders = [this] { + setExtendedBorders(m_extendedBorders->left(), m_extendedBorders->right(), m_extendedBorders->top(), m_extendedBorders->bottom()); + }; + updateExtendedBorders(); + connect(m_extendedBorders, &KWin::Borders::leftChanged, this, updateExtendedBorders); + connect(m_extendedBorders, &KWin::Borders::rightChanged, this, updateExtendedBorders); + connect(m_extendedBorders, &KWin::Borders::topChanged, this, updateExtendedBorders); + connect(m_extendedBorders, &KWin::Borders::bottomChanged, this, updateExtendedBorders); } - QWheelEvent *wheel = static_cast(event); - if (mousePosition(wheel->pos()) == PositionCenter) { - titlebarMouseWheelOperation(wheel->delta()); - return true; + connect(client().data(), &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateBorders, Qt::QueuedConnection); + updateBorders(); + if (!m_view.isNull()) { + m_view->setVisible(true); + m_view->lower(); + m_view->resize(m_item->width(), m_item->height()); + auto resizeWindow = [this] { + m_view->resize(m_item->width(), m_item->height()); + m_view->lower(); + m_view->update(); + }; + connect(m_item, &QQuickItem::widthChanged, this, resizeWindow); + connect(m_item, &QQuickItem::heightChanged, this, resizeWindow); + resizeWindow(); } - return false; } -void AuroraeClient::resize(const QSize &s) -{ - if (m_item) { - m_item->setWidth(s.width()); - m_item->setHeight(s.height()); - } - m_view->resize(s); -} - -void AuroraeClient::borders(int &left, int &right, int &top, int &bottom) const -{ - if (!m_item) { - left = right = top = bottom = 0; - return; - } - KWin::Borders *borders = nullptr; - if (maximizeMode() == MaximizeFull) { - borders = m_maximizedBorders; - } else { - borders = m_borders; - } - sizesFromBorders(borders, left, right, top, bottom); -} - -void AuroraeClient::padding(int &left, int &right, int &top, int &bottom) const -{ - if (!m_padding) { - left = right = top = bottom = 0; - return; - } - if (maximizeMode() == MaximizeFull) { - left = right = top = bottom = 0; - return; - } - sizesFromBorders(m_padding, left, right, top, bottom); -} - -void AuroraeClient::sizesFromBorders(const KWin::Borders *borders, int &left, int &right, int &top, int &bottom) const -{ - if (!borders) { - left = right = top = bottom = 0; - return; - } - left = borders->left(); - right = borders->right(); - top = borders->top(); - bottom = borders->bottom(); -} - -QSize AuroraeClient::minimumSize() const -{ - return m_view->minimumSize(); -} - -KDecorationDefines::Position AuroraeClient::mousePosition(const QPoint &point) const -{ - // based on the code from deKorator - int pos = PositionCenter; - if (isShade() || isMaximized()) { - return Position(pos); - } - - int borderLeft, borderTop, borderRight, borderBottom; - borders(borderLeft, borderRight, borderTop, borderBottom); - int paddingLeft, paddingTop, paddingRight, paddingBottom; - padding(paddingLeft, paddingRight, paddingTop, paddingBottom); - int titleEdgeLeft, titleEdgeRight, titleEdgeTop, titleEdgeBottom; - AuroraeFactory::instance()->theme()->titleEdges(titleEdgeLeft, titleEdgeTop, titleEdgeRight, titleEdgeBottom, false); - switch (AuroraeFactory::instance()->theme()->decorationPosition()) { - case DecorationTop: - borderTop = titleEdgeTop; - break; - case DecorationLeft: - borderLeft = titleEdgeLeft; - break; - case DecorationRight: - borderRight = titleEdgeRight; - break; - case DecorationBottom: - borderBottom = titleEdgeBottom; - break; - default: - break; // nothing - } - if (point.x() >= (m_view->width() - borderRight - paddingRight)) { - pos |= PositionRight; - } else if (point.x() <= borderLeft + paddingLeft) { - pos |= PositionLeft; - } - - if (point.y() >= m_view->height() - borderBottom - paddingBottom) { - pos |= PositionBottom; - } else if (point.y() <= borderTop + paddingTop ) { - pos |= PositionTop; - } - - return Position(pos); -} - -void AuroraeClient::menuClicked() -{ - showWindowMenu(QCursor::pos()); -} - -void AuroraeClient::appMenuClicked() -{ - showApplicationMenu(QCursor::pos()); -} - -void AuroraeClient::toggleShade() -{ - setShade(!isShade()); -} - -void AuroraeClient::toggleKeepAbove() -{ - setKeepAbove(!keepAbove()); -} - -void AuroraeClient::toggleKeepBelow() -{ - setKeepBelow(!keepBelow()); -} - -void AuroraeClient::titlePressed(int button, int buttons) -{ - titlePressed(static_cast(button), static_cast(buttons)); -} - -void AuroraeClient::titlePressed(Qt::MouseButton button, Qt::MouseButtons buttons) -{ - const QPoint cursor = QCursor::pos(); - QMouseEvent *event = new QMouseEvent(QEvent::MouseButtonPress, cursor - geometry().topLeft() + (m_padding ? QPoint(m_padding->left(), m_padding->top()) : QPoint(0, 0)), - cursor, button, buttons, Qt::NoModifier); - processMousePressEvent(event); - delete event; - event = nullptr; -} - -void AuroraeClient::themeChanged() -{ - m_item->deleteLater(); - m_item = AuroraeFactory::instance()->createQmlDecoration(this); - if (!m_item) { - m_borders = nullptr; - m_extendedBorders = nullptr; - m_maximizedBorders = nullptr; - m_padding = nullptr; - return; - } - - m_item->setParentItem(m_view->contentItem()); - m_item->setParent(m_view); - setupBorders(); - connect(m_item, SIGNAL(alphaChanged()), SLOT(slotAlphaChanged())); - slotAlphaChanged(); -} - -int AuroraeClient::doubleClickInterval() const -{ - return QApplication::doubleClickInterval(); -} - -void AuroraeClient::closeWindow() -{ - QMetaObject::invokeMethod(qobject_cast< KDecoration* >(this), "doCloseWindow", Qt::QueuedConnection); -} - -void AuroraeClient::doCloseWindow() -{ - KDecoration::closeWindow(); -} - -void AuroraeClient::maximize(int button) -{ - // a maximized window does not need to have a window decoration - // in that case we need to delay handling by one cycle - // BUG: 304870 - QMetaObject::invokeMethod(qobject_cast< KDecoration* >(this), - "doMaximzie", - Qt::QueuedConnection, - Q_ARG(int, button)); -} - -void AuroraeClient::doMaximzie(int button) -{ - KDecoration::maximize(static_cast(button)); -} - -void AuroraeClient::titlebarDblClickOperation() -{ - // the double click operation can result in a window being maximized - // see maximize - QMetaObject::invokeMethod(qobject_cast< KDecoration* >(this), "doTitlebarDblClickOperation", Qt::QueuedConnection); -} - -void AuroraeClient::doTitlebarDblClickOperation() -{ - KDecoration::titlebarDblClickOperation(); -} - -QVariant AuroraeClient::readConfig(const QString &key, const QVariant &defaultValue) +QVariant Decoration::readConfig(const QString &key, const QVariant &defaultValue) { KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("auroraerc")); - return config->group(AuroraeFactory::instance()->currentThemeName()).readEntry(key, defaultValue); + return config->group(QStringLiteral("Plastik")).readEntry(key, defaultValue); } -void AuroraeClient::slotAlphaChanged() +void Decoration::setupBorders(QQuickItem *item) { - if (!m_item) { - setAlphaEnabled(false); + m_borders = item->findChild(QStringLiteral("borders")); + m_maximizedBorders = item->findChild(QStringLiteral("maximizedBorders")); + m_extendedBorders = item->findChild(QStringLiteral("extendedBorders")); + m_padding = item->findChild(QStringLiteral("padding")); +} + +void Decoration::updateBorders() +{ + KWin::Borders *b = m_borders; + if (client()->isMaximized() && m_maximizedBorders) { + b = m_maximizedBorders; + } + if (!b) { return; } - QVariant alphaProperty = m_item->property("alpha"); - if (alphaProperty.isValid() && alphaProperty.canConvert()) { - setAlphaEnabled(alphaProperty.toBool()); - } else { - // by default all Aurorae themes use the alpha channel - setAlphaEnabled(true); - } + setBorders(b->left(), b->right(), b->top(), b->bottom()); } -QRegion AuroraeClient::region(KDecorationDefines::Region r) +void Decoration::paint(QPainter *painter) { - if (r != ExtendedBorderRegion) { - return QRegion(); - } - if (!m_item) { - return QRegion(); - } - if (isMaximized()) { - // empty region for maximized windows - return QRegion(); - } - int left, right, top, bottom; - left = right = top = bottom = 0; - sizesFromBorders(m_extendedBorders, left, right, top, bottom); - if (top == 0 && right == 0 && bottom == 0 && left == 0) { - // no extended borders - return QRegion(); - } - - int paddingLeft, paddingRight, paddingTop, paddingBottom; - paddingLeft = paddingRight = paddingTop = paddingBottom = 0; - padding(paddingLeft, paddingRight, paddingTop, paddingBottom); - QRect rect = this->rect().adjusted(paddingLeft, paddingTop, -paddingRight, -paddingBottom); - rect.translate(-paddingLeft, -paddingTop); - - return QRegion(rect.adjusted(-left, -top, right, bottom)).subtract(rect); + QMutexLocker locker(&m_mutex); + painter->fillRect(rect(), Qt::transparent); + // TODO: remove Shadow + painter->drawImage(rect(), m_buffer); } -bool AuroraeClient::animationsSupported() const +void Decoration::hoverEnterEvent(QHoverEvent *event) { - return compositingActive(); -} - -void AuroraeClient::render(QPaintDevice *device, const QRegion &sourceRegion) -{ - QMutexLocker locker(AuroraeFactory::instance()->mutex()); - QPainter painter(device); - painter.setClipRegion(sourceRegion); - painter.drawImage(QPoint(0, 0), m_buffer); -} - -void AuroraeClient::setupBorders() -{ - if (!m_item) { - return; + if (m_view) { + event->setAccepted(false); + QCoreApplication::sendEvent(m_view.data(), event); } - m_borders = m_item->findChild(QStringLiteral("borders")); - m_maximizedBorders = m_item->findChild(QStringLiteral("maximizedBorders")); - m_extendedBorders = m_item->findChild(QStringLiteral("extendedBorders")); - m_padding = m_item->findChild(QStringLiteral("padding")); + KDecoration2::Decoration::hoverEnterEvent(event); } -} // namespace Aurorae +void Decoration::hoverLeaveEvent(QHoverEvent *event) +{ + if (m_view) { + event->setAccepted(false); + QCoreApplication::sendEvent(m_view.data(), event); + } + KDecoration2::Decoration::hoverLeaveEvent(event); +} + +void Decoration::hoverMoveEvent(QHoverEvent *event) +{ + if (m_view) { + QMouseEvent ev(QEvent::MouseMove, event->posF(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QCoreApplication::sendEvent(m_view.data(), &ev); + } + KDecoration2::Decoration::hoverMoveEvent(event); +} + +void Decoration::mouseMoveEvent(QMouseEvent *event) +{ + if (m_view) { + event->setAccepted(false); + QCoreApplication::sendEvent(m_view.data(), event); + } + KDecoration2::Decoration::mouseMoveEvent(event); +} + +void Decoration::mousePressEvent(QMouseEvent *event) +{ + if (m_view) { + event->setAccepted(false); + QCoreApplication::sendEvent(m_view.data(), event); + } + KDecoration2::Decoration::mousePressEvent(event); +} + +void Decoration::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_view) { + event->setAccepted(false); + QCoreApplication::sendEvent(m_view.data(), event); + } + KDecoration2::Decoration::mouseReleaseEvent(event); +} + +void Decoration::installTitleItem(QQuickItem *item) +{ + auto update = [this, item] { + QRect rect = item->mapRectToScene(item->childrenRect()).toRect(); + if (rect.isNull()) { + rect = item->parentItem()->mapRectToScene(QRectF(item->x(), item->y(), item->width(), item->height())).toRect(); + } + setTitleRect(rect); + }; + update(); + connect(item, &QQuickItem::widthChanged, this, update); + connect(item, &QQuickItem::heightChanged, this, update); + connect(item, &QQuickItem::xChanged, this, update); + connect(item, &QQuickItem::yChanged, this, update); +} + +} #include "aurorae.moc" diff --git a/clients/aurorae/src/aurorae.desktop b/clients/aurorae/src/aurorae.desktop deleted file mode 100644 index 9e4e99f3ff..0000000000 --- a/clients/aurorae/src/aurorae.desktop +++ /dev/null @@ -1,68 +0,0 @@ -[Desktop Entry] -Name=Aurorae Decoration Theme Engine -Name[ar]=محرك شفق لسمات التزيين -Name[ast]=Motor de temes de decoración Aurorae -Name[bg]=Теми за декорация на прозорци Aurorae -Name[bs]=Aurore, tematski motor dekoracija -Name[ca]=Motor del tema de decoració Aurorae -Name[ca@valencia]=Motor del tema de decoració Aurorae -Name[cs]=Stroj motivů dekorace Aurorae -Name[csb]=Mòtór dekòracëji wëzdrzatkù Aurorae -Name[da]=Temamotor til Aurorae-dekorationen -Name[de]=Aurorae-Dekorationsdesign-Engine -Name[el]=Μηχανισμός διακόσμησης θεμάτων Aurorae -Name[en_GB]=Auroræ Decoration Theme Engine -Name[eo]=Aurorae Ornamaĵ-etosa Modulo -Name[es]=Motor de temas de decoración Aurorae -Name[et]=Aurorae dekoratsioonide teema mootor -Name[eu]=Aurorae apainketa-gaiaren motorra -Name[fi]=Kehysten teemamoottori Aurorae -Name[fr]=Moteur de thèmes pour la décoration « Aurorae » -Name[fy]=Aurorae dekoraasje tema motor -Name[ga]=Inneall Téama Maisiúcháin Aurorae -Name[gl]=Motor de temas de decoración Aurorae -Name[he]=מנוע ערכת התצוגה Aurorae Decoration -Name[hr]=Tematski mehanizam za ukrase Aurorae -Name[hu]=Aurorae ablakdekorációs témamodul -Name[ia]=Motor de thema de decoration Aurorae -Name[id]=Mesin Tema Dekorasi Aurorae -Name[is]=Aurorae skjáskreytiþemavél -Name[it]=Motore dei temi decorativi Aurorae -Name[ja]=オーロラ装飾テーマエンジン -Name[kk]=Aurorae безендіру нақыш теігі -Name[km]=ម៉ាស៊ីន​ស្បែក​តុបតែង​ Aurorae -Name[kn]=ಅರೋರೆ ಪರಿಸರ ವಿನ್ಯಾಸ(ಥೀಮ್) ಎಂಜಿನ್ -Name[ko]=Aurorae 장식 테마 엔진 -Name[lt]=Aurorae dekoracijos temos variklis -Name[lv]=Aurorae dekorācijas tēmu dzinējs -Name[ml]=അറോറ അണിയിച്ചൊരുക്കാനുള്ള പ്രമേയ എഞ്ചിന്‍ -Name[mr]=ओरोरा सजावट शैली इंजिन -Name[nb]=Aurorae motor for dekorasjonstema -Name[nds]=Aurorae Dekoratschonen-Musterkarn -Name[nl]=Aurorae decoratiethema-engine -Name[nn]=Motor for pynting med temaet Aurorae -Name[pa]=ਔਰੋਰਾਈ ਸਜਾਵਟ ਥੀਮ ਇੰਜਣ -Name[pl]=Silnik zestawu ozdób Aurora -Name[pt]=Motor do Tema de Decoração Aurorae -Name[pt_BR]=Mecanismo do tema de decoração Aurorae -Name[ro]=Motor pentru tematici de decorare Aurorae -Name[ru]=Движок оформлений окон Aurorae -Name[si]=Aurorae සැරසිලි තේමා එන්ජිම -Name[sk]=Aurorae témy dekorácie -Name[sl]=Pogon Aurorae za teme okraskov -Name[sr]=Ауроре, тематски мотор декорација -Name[sr@ijekavian]=Ауроре, тематски мотор декорација -Name[sr@ijekavianlatin]=Aurore, tematski motor dekoracija -Name[sr@latin]=Aurore, tematski motor dekoracija -Name[sv]=Aurora dekorationstemagränssnitt -Name[tg]=Системаи мавзӯъҳои аврора -Name[th]=กลไกชุดตกแต่ง Aurorae -Name[tr]=Aurorae Dekorasyon Teması Motoru -Name[ug]=Aurorae زىننەتلەش ئۆرنەك ماتورى -Name[uk]=Рушій декорації тем Aurorae -Name[vi]=Cơ chế sắc thái trang trí Aurorae -Name[wa]=Moteur di tinme di gåyotaedje Aurorae -Name[x-test]=xxAurorae Decoration Theme Enginexx -Name[zh_CN]=Aurorae 装饰主题引擎 -Name[zh_TW]=Aurorae 裝飾主題引擎 -X-KDE-PluginInfo-Name=aurorae diff --git a/clients/aurorae/src/aurorae.h b/clients/aurorae/src/aurorae.h index 8fa835ff68..ce513a98f3 100644 --- a/clients/aurorae/src/aurorae.h +++ b/clients/aurorae/src/aurorae.h @@ -18,19 +18,16 @@ along with this program. If not, see . #ifndef AURORAE_H #define AURORAE_H -#include "themeconfig.h" +#include +#include +#include -#include -#include - -class QMutex; class QOpenGLFramebufferObject; class QQmlComponent; class QQmlEngine; class QQuickItem; class QQuickWindow; -class KConfig; -class KConfigGroup; +class QWindow; namespace KWin { @@ -39,144 +36,44 @@ class Borders; namespace Aurorae { -class AuroraeTheme; -class AuroraeClient; -class AuroraeFactory : public KDecorationFactory +class Decoration : public KDecoration2::Decoration { Q_OBJECT public: - ~AuroraeFactory(); + explicit Decoration(QObject *parent = nullptr, const QVariantList &args = QVariantList()); + virtual ~Decoration(); - static AuroraeFactory* instance(); - static QObject *createInstance(QWidget *, QObject *, const QList &); - KDecoration *createDecoration(KDecorationBridge*); - bool supports(Ability ability) const; - virtual QList< BorderSize > borderSizes() const; - - AuroraeTheme *theme() const { - return m_theme; - } - QQuickItem *createQmlDecoration(AuroraeClient *client); - const QString ¤tThemeName() const { - return m_themeName; - } - - QMutex *mutex() { - return m_mutex.data(); - } - -private: - enum EngineType { - AuroraeEngine, - QMLEngine - }; - explicit AuroraeFactory(QObject *parent = nullptr); - void init(); - void initAurorae(KConfig &conf, KConfigGroup &group); - void initQML(const KConfigGroup& group); - -Q_SIGNALS: - void buttonsChanged(); - void titleFontChanged(); - void configChanged(); - -private Q_SLOTS: - void updateConfiguration(); - -private: - static AuroraeFactory *s_instance; - - AuroraeTheme *m_theme; - QQmlEngine *m_engine; - QQmlComponent *m_component; - EngineType m_engineType; - QString m_themeName; - QScopedPointer m_mutex; -}; - -class AuroraeClient : public KDecoration -{ - Q_OBJECT - Q_PROPERTY(QRect geometry READ geometry) - Q_PROPERTY(int height READ height) - Q_PROPERTY(bool closeable READ isCloseable CONSTANT) - Q_PROPERTY(bool maximizeable READ isMaximizable CONSTANT) - Q_PROPERTY(bool minimizeable READ isMinimizable CONSTANT) - Q_PROPERTY(bool modal READ isModal) - Q_PROPERTY(bool moveable READ isMovable CONSTANT) - Q_PROPERTY(bool preview READ isPreview CONSTANT) - Q_PROPERTY(bool resizeable READ isResizable CONSTANT) - Q_PROPERTY(bool shadeable READ isShadeable) - Q_PROPERTY(bool providesContextHelp READ providesContextHelp) - Q_PROPERTY(bool appMenu READ menuAvailable NOTIFY appMenuAvailableChanged) - Q_PROPERTY(QRect transparentRect READ transparentRect) - Q_PROPERTY(int width READ width) - Q_PROPERTY(qulonglong windowId READ windowId CONSTANT) - Q_PROPERTY(int doubleClickInterval READ doubleClickInterval) - Q_PROPERTY(bool animationsSupported READ animationsSupported CONSTANT) - // TODO: window tabs - they suck for dynamic features -public: - AuroraeClient(KDecorationBridge* bridge, KDecorationFactory* factory); - virtual ~AuroraeClient(); - virtual bool eventFilter(QObject *object, QEvent *event); - virtual void borders(int& left, int& right, int& top, int& bottom) const; - virtual void init(); - virtual QSize minimumSize() const; - virtual Position mousePosition(const QPoint& p) const; - virtual void resize(const QSize& s); - // optional overrides - virtual void padding(int &left, int &right, int &top, int &bottom) const; - int doubleClickInterval() const; - - bool animationsSupported() const; + void paint(QPainter *painter) override; Q_INVOKABLE QVariant readConfig(const QString &key, const QVariant &defaultValue = QVariant()); - virtual void render(QPaintDevice *device, const QRegion &sourceRegion); - -Q_SIGNALS: - void buttonsChanged(); - /** - * Signal emitted when the decoration's configuration might have changed. - * A decoration could reload it's configuration when this signal is emitted. - **/ - void configChanged(); - void fontChanged(); - void appMenuAvailableChanged(); - public Q_SLOTS: - void menuClicked(); - void appMenuClicked(); - void toggleShade(); - void toggleKeepAbove(); - void toggleKeepBelow(); - void titlePressed(int button, int buttons); - void titlePressed(Qt::MouseButton button, Qt::MouseButtons buttons); - void closeWindow(); - void titlebarDblClickOperation(); - void maximize(int button); + void init() override; + void installTitleItem(QQuickItem *item); - QRegion region(KDecorationDefines::Region r); - -private Q_SLOTS: - void themeChanged(); - void doCloseWindow(); - void doTitlebarDblClickOperation(); - void doMaximzie(int button); - void slotAlphaChanged(); +protected: + void hoverEnterEvent(QHoverEvent *event) override; + void hoverLeaveEvent(QHoverEvent *event) override; + void hoverMoveEvent(QHoverEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; private: - void sizesFromBorders(const KWin::Borders *borders, int &left, int &right, int &top, int &bottom) const; - void setupBorders(); - QQuickWindow *m_view; - QQuickItem *m_item; + void setupBorders(QQuickItem *item); + void updateBorders(); QScopedPointer m_fbo; QImage m_buffer; + QScopedPointer m_decorationWindow; + QScopedPointer m_view; + QQuickItem *m_item; KWin::Borders *m_borders; KWin::Borders *m_maximizedBorders; KWin::Borders *m_extendedBorders; KWin::Borders *m_padding; + QString m_themeName; + QMutex m_mutex; }; } diff --git a/clients/aurorae/src/aurorae.json b/clients/aurorae/src/aurorae.json new file mode 100644 index 0000000000..5fbeb5ab9f --- /dev/null +++ b/clients/aurorae/src/aurorae.json @@ -0,0 +1,14 @@ +{ + "Type": "Service", + "X-KDE-Library": "kwin5_aurorae", + "X-KDE-PluginInfo-EnabledByDefault": true, + "X-KDE-PluginInfo-Name": "org.kde.kwin.aurorae", + "X-KDE-ServiceTypes": [ + "org.kde.kdecoration2" + ], + "org.kde.kdecoration2": { + "blur": true, + "themes": true, + "defaultTheme": "kwin4_decoration_qml_plastik" + } +} diff --git a/clients/aurorae/src/decorationoptions.cpp b/clients/aurorae/src/decorationoptions.cpp index fb3da425e0..bdf57d54c7 100644 --- a/clients/aurorae/src/decorationoptions.cpp +++ b/clients/aurorae/src/decorationoptions.cpp @@ -15,19 +15,55 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "decorationoptions.h" -#include +#include +#include +#include +#include namespace KWin { +ColorSettings::ColorSettings(const QPalette &pal) +{ + init(pal); +} + +void ColorSettings::update(const QPalette &pal) +{ + init(pal); +} + +void ColorSettings::init(const QPalette &pal) +{ + m_palette = pal; + KConfigGroup wmConfig(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("WM")); + m_activeFrameColor = wmConfig.readEntry("frame", pal.color(QPalette::Active, QPalette::Background)); + m_inactiveFrameColor = wmConfig.readEntry("inactiveFrame", m_activeFrameColor); + m_activeTitleBarColor = wmConfig.readEntry("activeBackground", pal.color(QPalette::Active, QPalette::Highlight)); + m_inactiveTitleBarColor = wmConfig.readEntry("inactiveBackground", m_inactiveFrameColor); + m_activeTitleBarBlendColor = wmConfig.readEntry("activeBlend", m_activeTitleBarColor.dark(110)); + m_inactiveTitleBarBlendColor = wmConfig.readEntry("inactiveBlend", m_inactiveTitleBarColor.dark(110)); + m_activeFontColor = wmConfig.readEntry("activeForeground", pal.color(QPalette::Active, QPalette::HighlightedText)); + m_inactiveFontColor = wmConfig.readEntry("inactiveForeground", m_activeFontColor.dark()); + m_activeButtonColor = wmConfig.readEntry("activeTitleBtnBg", m_activeFrameColor.light(130)); + m_inactiveButtonColor = wmConfig.readEntry("inactiveTitleBtnBg", m_inactiveFrameColor.light(130)); + m_activeHandle = wmConfig.readEntry("handle", m_activeFrameColor); + m_inactiveHandle = wmConfig.readEntry("inactiveHandle", m_activeHandle); +} + + DecorationOptions::DecorationOptions(QObject *parent) : QObject(parent) , m_active(true) , m_decoration(nullptr) + , m_colors(ColorSettings(QPalette())) { connect(this, &DecorationOptions::decorationChanged, this, &DecorationOptions::slotActiveChanged); connect(this, &DecorationOptions::decorationChanged, this, &DecorationOptions::colorsChanged); connect(this, &DecorationOptions::decorationChanged, this, &DecorationOptions::fontChanged); + connect(KDecoration2::DecorationSettings::self(), &KDecoration2::DecorationSettings::fontChanged, this, &DecorationOptions::fontChanged); + connect(KDecoration2::DecorationSettings::self(), &KDecoration2::DecorationSettings::decorationButtonsLeftChanged, this, &DecorationOptions::titleButtonsChanged); + connect(KDecoration2::DecorationSettings::self(), &KDecoration2::DecorationSettings::decorationButtonsRightChanged, this, &DecorationOptions::titleButtonsChanged); } DecorationOptions::~DecorationOptions() @@ -36,89 +72,101 @@ DecorationOptions::~DecorationOptions() QColor DecorationOptions::borderColor() const { - return KDecoration::options()->color(KDecorationDefines::ColorFrame, m_active); + return m_active ? m_colors.activeFrame() : m_colors.inactiveFrame(); } QColor DecorationOptions::buttonColor() const { - return KDecoration::options()->color(KDecorationDefines::ColorButtonBg, m_active); + return m_active ? m_colors.activeButtonColor() : m_colors.inactiveButtonColor(); } QColor DecorationOptions::fontColor() const { - return KDecoration::options()->color(KDecorationDefines::ColorFont, m_active); + return m_active ? m_colors.activeFont() : m_colors.inactiveFont(); } QColor DecorationOptions::resizeHandleColor() const { - return KDecoration::options()->color(KDecorationDefines::ColorHandle, m_active); + return m_active ? m_colors.activeHandle() : m_colors.inactiveHandle(); } QColor DecorationOptions::titleBarBlendColor() const { - return KDecoration::options()->color(KDecorationDefines::ColorTitleBlend, m_active); + return m_active ? m_colors.activeTitleBarBlendColor() : m_colors.inactiveTitleBarBlendColor(); } QColor DecorationOptions::titleBarColor() const { - return KDecoration::options()->color(KDecorationDefines::ColorTitleBar, m_active); + return m_active ? m_colors.activeTitleBarColor() : m_colors.inactiveTitleBarColor(); } QFont DecorationOptions::titleFont() const { - return KDecoration::options()->font(m_active); + return KDecoration2::DecorationSettings::self()->font(); +} + +static int decorationButton(KDecoration2::DecorationButtonType type) +{ + switch (type) { + case KDecoration2::DecorationButtonType::Menu: + return DecorationOptions::DecorationButtonMenu; + case KDecoration2::DecorationButtonType::ApplicationMenu: + return DecorationOptions::DecorationButtonApplicationMenu; + case KDecoration2::DecorationButtonType::OnAllDesktops: + return DecorationOptions::DecorationButtonOnAllDesktops; + case KDecoration2::DecorationButtonType::Minimize: + return DecorationOptions::DecorationButtonMinimize; + case KDecoration2::DecorationButtonType::Maximize: + return DecorationOptions::DecorationButtonMaximizeRestore; + case KDecoration2::DecorationButtonType::Close: + return DecorationOptions::DecorationButtonClose; + case KDecoration2::DecorationButtonType::QuickHelp: + return DecorationOptions::DecorationButtonQuickHelp; + case KDecoration2::DecorationButtonType::Shade: + return DecorationOptions::DecorationButtonShade; + case KDecoration2::DecorationButtonType::KeepBelow: + return DecorationOptions::DecorationButtonKeepBelow; + case KDecoration2::DecorationButtonType::KeepAbove: + return DecorationOptions::DecorationButtonKeepAbove; + default: + return DecorationOptions::DecorationButtonNone; + } } QList DecorationOptions::titleButtonsLeft() const { - QList buttons; - if (KDecoration::options()->customButtonPositions()) { - buttons = KDecoration::options()->titleButtonsLeft(); - } else { - buttons = KDecorationOptions::defaultTitleButtonsLeft(); - } QList ret; - for (auto it : buttons) { - ret << static_cast(it); + for (auto it : KDecoration2::DecorationSettings::self()->decorationButtonsLeft()) { + ret << decorationButton(it); } return ret; } QList DecorationOptions::titleButtonsRight() const { - QList buttons; - if (KDecoration::options()->customButtonPositions()) { - buttons = KDecoration::options()->titleButtonsRight(); - } else { - buttons = KDecorationOptions::defaultTitleButtonsRight(); - } QList ret; - for (auto it : buttons) { - ret << static_cast(it); + for (auto it : KDecoration2::DecorationSettings::self()->decorationButtonsRight()) { + ret << decorationButton(it); } return ret; } -QObject *DecorationOptions::decoration() const +KDecoration2::Decoration *DecorationOptions::decoration() const { return m_decoration; } -void DecorationOptions::setDecoration(QObject *decoration) +void DecorationOptions::setDecoration(KDecoration2::Decoration *decoration) { if (m_decoration == decoration) { return; } if (m_decoration) { // disconnect from existing decoration - disconnect(m_decoration, SIGNAL(activeChanged()), this, SLOT(slotActiveChanged())); - disconnect(m_decoration, SIGNAL(buttonsChanged()), this, SIGNAL(titleButtonsChanged())); - disconnect(m_decoration, SIGNAL(fontChanged()), this, SIGNAL(fontChanged())); + disconnect(m_decoration->client().data(), &KDecoration2::DecoratedClient::activeChanged, this, &DecorationOptions::slotActiveChanged); } m_decoration = decoration; - connect(m_decoration, SIGNAL(activeChanged()), SLOT(slotActiveChanged())); - connect(m_decoration, SIGNAL(buttonsChanged()), SIGNAL(titleButtonsChanged())); - connect(m_decoration, SIGNAL(fontChanged()), SIGNAL(fontChanged())); + connect(m_decoration->client().data(), &KDecoration2::DecoratedClient::activeChanged, this, &DecorationOptions::slotActiveChanged); emit decorationChanged(); } @@ -127,10 +175,10 @@ void DecorationOptions::slotActiveChanged() if (!m_decoration) { return; } - if (m_active == m_decoration->property("active").toBool()) { + if (m_active == m_decoration->client()->isActive()) { return; } - m_active = m_decoration->property("active").toBool(); + m_active = m_decoration->client()->isActive(); emit colorsChanged(); emit fontChanged(); } diff --git a/clients/aurorae/src/decorationoptions.h b/clients/aurorae/src/decorationoptions.h index 8f7bced58b..cf3f5f496e 100644 --- a/clients/aurorae/src/decorationoptions.h +++ b/clients/aurorae/src/decorationoptions.h @@ -17,13 +17,89 @@ along with this program. If not, see . #ifndef KWIN_DECORATION_OPTIONS_H #define KWIN_DECORATION_OPTIONS_H +#include + #include #include #include +#include namespace KWin { +// TODO: move to deco API +class ColorSettings +{ +public: + ColorSettings(const QPalette &pal); + + void update(const QPalette &pal); + + const QColor &titleBarColor(bool active) const { + return active ? m_activeTitleBarColor : m_inactiveTitleBarColor; + } + const QColor &activeTitleBarColor() const { + return m_activeTitleBarColor; + } + const QColor &inactiveTitleBarColor() const { + return m_inactiveTitleBarColor; + } + const QColor &activeTitleBarBlendColor() const { + return m_activeTitleBarBlendColor; + } + const QColor &inactiveTitleBarBlendColor() const { + return m_inactiveTitleBarBlendColor; + } + const QColor &frame(bool active) const { + return active ? m_activeFrameColor : m_inactiveFrameColor; + } + const QColor &activeFrame() const { + return m_activeFrameColor; + } + const QColor &inactiveFrame() const { + return m_inactiveFrameColor; + } + const QColor &font(bool active) const { + return active ? m_activeFontColor : m_inactiveFontColor; + } + const QColor &activeFont() const { + return m_activeFontColor; + } + const QColor &inactiveFont() const { + return m_inactiveFontColor; + } + const QColor &activeButtonColor() const { + return m_activeButtonColor; + } + const QColor &inactiveButtonColor() const { + return m_inactiveButtonColor; + } + const QColor &activeHandle() const { + return m_activeHandle; + } + const QColor &inactiveHandle() const { + return m_inactiveHandle; + } + const QPalette &palette() const { + return m_palette; + } +private: + void init(const QPalette &pal); + QColor m_activeTitleBarColor; + QColor m_inactiveTitleBarColor; + QColor m_activeTitleBarBlendColor; + QColor m_inactiveTitleBarBlendColor; + QColor m_activeFrameColor; + QColor m_inactiveFrameColor; + QColor m_activeFontColor; + QColor m_inactiveFontColor; + QColor m_activeButtonColor; + QColor m_inactiveButtonColor; + QColor m_activeHandle; + QColor m_inactiveHandle; + QPalette m_palette; +}; + /** * @short Common Window Decoration Options. * @@ -60,7 +136,7 @@ class DecorationOptions : public QObject * * Best pass the decoration object available as a context property to this property. **/ - Q_PROPERTY(QObject *deco READ decoration WRITE setDecoration NOTIFY decorationChanged) + Q_PROPERTY(KDecoration2::Decoration *deco READ decoration WRITE setDecoration NOTIFY decorationChanged) /** * The color for the titlebar depending on the decoration's active state. **/ @@ -149,8 +225,8 @@ public: QFont titleFont() const; QList titleButtonsLeft() const; QList titleButtonsRight() const; - QObject *decoration() const; - void setDecoration(QObject *decoration); + KDecoration2::Decoration *decoration() const; + void setDecoration(KDecoration2::Decoration *decoration); Q_SIGNALS: void colorsChanged(); @@ -163,7 +239,8 @@ private Q_SLOTS: private: bool m_active; - QObject *m_decoration; + KDecoration2::Decoration *m_decoration; + ColorSettings m_colors; }; class Borders : public QObject diff --git a/clients/aurorae/src/qml/AppMenuButton.qml b/clients/aurorae/src/qml/AppMenuButton.qml index 4634e2dee1..e60579a804 100644 --- a/clients/aurorae/src/qml/AppMenuButton.qml +++ b/clients/aurorae/src/qml/AppMenuButton.qml @@ -21,9 +21,9 @@ import org.kde.kwin.decoration 0.1 DecorationButton { id: appMenuButton buttonType: DecorationOptions.DecorationButtonApplicationMenu - visible: decoration.appMenu + visible: false //decoration.appMenu KQuickControlsAddons.QIconItem { - icon: decoration.icon + icon: decoration.client.icon anchors.fill: parent } } diff --git a/clients/aurorae/src/qml/AuroraeButton.qml b/clients/aurorae/src/qml/AuroraeButton.qml index c2a835faba..5d2968bafd 100644 --- a/clients/aurorae/src/qml/AuroraeButton.qml +++ b/clients/aurorae/src/qml/AuroraeButton.qml @@ -103,7 +103,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonActive - property bool shown: (decoration.active || !buttonSvg.supportsInactive) && ((!pressed && !toggled) || !buttonSvg.supportsPressed) && (!hovered || !buttonSvg.supportsHover) && (enabled || !buttonSvg.supportsDeactivated) + property bool shown: (decoration.client.active || !buttonSvg.supportsInactive) && ((!pressed && !toggled) || !buttonSvg.supportsPressed) && (!hovered || !buttonSvg.supportsHover) && (enabled || !buttonSvg.supportsDeactivated) anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "active" @@ -116,7 +116,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonActiveHover - property bool shown: hovered && !pressed && !toggled && buttonSvg.supportsHover && (decoration.active || !buttonSvg.supportsInactiveHover) + property bool shown: hovered && !pressed && !toggled && buttonSvg.supportsHover && (decoration.client.active || !buttonSvg.supportsInactiveHover) anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "hover" @@ -129,7 +129,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonActivePressed - property bool shown: (toggled || pressed) && buttonSvg.supportsPressed && (decoration.active || !buttonSvg.supportsInactivePressed) + property bool shown: (toggled || pressed) && buttonSvg.supportsPressed && (decoration.client.active || !buttonSvg.supportsInactivePressed) anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "pressed" @@ -142,7 +142,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonActiveDeactivated - property bool shown: !enabled && buttonSvg.supportsDeactivated && (decoration.active || !buttonSvg.supportsInactiveDeactivated) + property bool shown: !enabled && buttonSvg.supportsDeactivated && (decoration.client.active || !buttonSvg.supportsInactiveDeactivated) anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "deactivated" @@ -155,7 +155,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonInactive - property bool shown: !decoration.active && buttonSvg.supportsInactive && !hovered && !pressed && !toggled && enabled + property bool shown: !decoration.client.active && buttonSvg.supportsInactive && !hovered && !pressed && !toggled && enabled anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "inactive" @@ -168,7 +168,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonInactiveHover - property bool shown: !decoration.active && hovered && !pressed && !toggled && buttonSvg.supportsInactiveHover + property bool shown: !decoration.client.active && hovered && !pressed && !toggled && buttonSvg.supportsInactiveHover anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "hover-inactive" @@ -181,7 +181,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonInactivePressed - property bool shown: !decoration.active && (toggled || pressed) && buttonSvg.supportsInactivePressed + property bool shown: !decoration.client.active && (toggled || pressed) && buttonSvg.supportsInactivePressed anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "pressed-inactive" @@ -194,7 +194,7 @@ DecorationButton { } PlasmaCore.FrameSvgItem { id: buttonInactiveDeactivated - property bool shown: !decoration.active && !enabled && buttonSvg.supportsInactiveDeactivated + property bool shown: !decoration.client.active && !enabled && buttonSvg.supportsInactiveDeactivated anchors.fill: parent imagePath: buttonSvg.imagePath prefix: "deactivated-inactive" diff --git a/clients/aurorae/src/qml/AuroraeButtonGroup.qml b/clients/aurorae/src/qml/AuroraeButtonGroup.qml index 44792cdc65..e2eacc43b8 100644 --- a/clients/aurorae/src/qml/AuroraeButtonGroup.qml +++ b/clients/aurorae/src/qml/AuroraeButtonGroup.qml @@ -55,6 +55,6 @@ Item { } anchors { top: root.top - topMargin: (decoration.maximized ? auroraeTheme.titleEdgeTopMaximized : auroraeTheme.titleEdgeTop + root.padding.top) + auroraeTheme.buttonMarginTop + topMargin: (decoration.client.maximized ? auroraeTheme.titleEdgeTopMaximized : auroraeTheme.titleEdgeTop + root.padding.top) + auroraeTheme.buttonMarginTop } } diff --git a/clients/aurorae/src/qml/AuroraeMaximizeButton.qml b/clients/aurorae/src/qml/AuroraeMaximizeButton.qml index 1f99db7246..c40cce6131 100644 --- a/clients/aurorae/src/qml/AuroraeMaximizeButton.qml +++ b/clients/aurorae/src/qml/AuroraeMaximizeButton.qml @@ -28,7 +28,7 @@ Item { id: maximizeButton anchors.fill: parent buttonType: DecorationOptions.DecorationButtonMaximizeRestore - opacity: (!decoration.maximized || auroraeTheme.restoreButtonPath == "") ? 1 : 0 + opacity: (!decoration.client.maximized || auroraeTheme.restoreButtonPath == "") ? 1 : 0 hovered: button.hovered pressed: button.pressed toggled: button.toggled @@ -42,7 +42,7 @@ Item { id: restoreButton anchors.fill: parent buttonType: DecorationOptions.DecorationButtonMaximizeRestore + 100 - opacity: (decoration.maximized && auroraeTheme.restoreButtonPath != "") ? 1 : 0 + opacity: (decoration.client.maximized && auroraeTheme.restoreButtonPath != "") ? 1 : 0 hovered: button.hovered pressed: button.pressed toggled: button.toggled @@ -63,7 +63,7 @@ Item { onPressed: button.pressed = true onReleased: button.pressed = false onClicked: { - decoration.maximize(mouse.button); + decoration.requestMaximize(mouse.button); } } } diff --git a/clients/aurorae/src/qml/Decoration.qml b/clients/aurorae/src/qml/Decoration.qml index 261a9b09c4..eee025e8a1 100644 --- a/clients/aurorae/src/qml/Decoration.qml +++ b/clients/aurorae/src/qml/Decoration.qml @@ -31,11 +31,6 @@ Item { objectName: "padding" } property bool alpha: true - - MouseArea { - anchors.fill: parent - hoverEnabled: true - onPressed: decoration.titlePressed(mouse.button, mouse.buttons) - onDoubleClicked: decoration.titlebarDblClickOperation() - } + width: decoration.client.width + decoration.borderLeft + decoration.borderRight + height: decoration.client.height + decoration.borderTop + decoration.borderBottom } diff --git a/clients/aurorae/src/qml/DecorationButton.qml b/clients/aurorae/src/qml/DecorationButton.qml index 9e707fa6c0..e1d9629810 100644 --- a/clients/aurorae/src/qml/DecorationButton.qml +++ b/clients/aurorae/src/qml/DecorationButton.qml @@ -26,11 +26,11 @@ Item { enabled: { switch (button.buttonType) { case DecorationOptions.DecorationButtonClose: - return decoration.closeable; + return decoration.client.closeable; case DecorationOptions.DecorationButtonMaximizeRestore: - return decoration.maximizeable; + return decoration.client.maximizeable; case DecorationOptions.DecorationButtonMinimize: - return decoration.minimizeable; + return decoration.client.minimizeable; case DecorationOptions.DecorationButtonExplicitSpacer: return false; default: @@ -58,93 +58,93 @@ Item { switch (button.buttonType) { case DecorationOptions.DecorationButtonMenu: // menu - decoration.menuClicked(); + decoration.requestShowWindowMenu(); break; case DecorationOptions.DecorationButtonApplicationMenu: // app menu - decoration.appMenuClicked(); +// decoration.appMenuClicked(); break; case DecorationOptions.DecorationButtonOnAllDesktops: // all desktops - decoration.toggleOnAllDesktops(); + decoration.requestToggleOnAllDesktops(); break; case DecorationOptions.DecorationButtonQuickHelp: // help - decoration.showContextHelp(); + decoration.requestContextHelp(); break; case DecorationOptions.DecorationButtonMinimize: // minimize - decoration.minimize(); + decoration.requestMinimize(); break; case DecorationOptions.DecorationButtonMaximizeRestore: // maximize - decoration.maximize(mouse.button); + decoration.requestMaximize(mouse.button); break; case DecorationOptions.DecorationButtonClose: // close - decoration.closeWindow(); + decoration.requestClose(); break; case DecorationOptions.DecorationButtonKeepAbove: // keep above - decoration.toggleKeepAbove(); + decoration.requestToggleKeepAbove(); break; case DecorationOptions.DecorationButtonKeepBelow: // keep below - decoration.toggleKeepBelow(); + decoration.requestToggleKeepBelow(); break; case DecorationOptions.DecorationButtonShade: // shade - decoration.toggleShade(); + decoration.requestToggleShade(); break; } } onDoubleClicked: { if (button.buttonType == DecorationOptions.DecorationButtonMenu) { - decoration.closeWindow(); + decoration.requestClose(); } } Component.onCompleted: { switch (button.buttonType) { case DecorationOptions.DecorationButtonOnAllDesktops: // all desktops - button.toggled = decoration.onAllDesktops; + button.toggled = decoration.client.onAllDesktops; break; case DecorationOptions.DecorationButtonKeepAbove: - button.toggled = decoration.keepAbove; + button.toggled = decoration.client.keepAbove; break; case DecorationOptions.DecorationButtonKeepBelow: - button.toggled = decoration.keepBelow; + button.toggled = decoration.client.keepBelow; break; case DecorationOptions.DecorationButtonShade: - button.toggled = decoration.shade; + button.toggled = decoration.client.shaded; break; } } Connections { - target: decoration - onShadeChanged: { + target: decoration.client + onShadedChanged: { if (button.buttonType != DecorationOptions.DecorationButtonShade) { return; } - button.toggled = decoration.shade; + button.toggled = decoration.client.shaded; } onKeepBelowChanged: { if (button.buttonType != DecorationOptions.DecorationButtonKeepBelow) { return; } - button.toggled = decoration.keepBelow; + button.toggled = decoration.client.keepBelow; } onKeepAboveChanged: { if (button.buttonType != DecorationOptions.DecorationButtonKeepAbove) { return; } - button.toggled = decoration.keepAbove; + button.toggled = decoration.client.keepAbove; } onDesktopChanged: { if (button.buttonType != DecorationOptions.DecorationButtonOnAllDesktops) { return; } - button.toggled = decoration.onAllDesktops; + button.toggled = decoration.client.onAllDesktops; } } } diff --git a/clients/aurorae/src/qml/MenuButton.qml b/clients/aurorae/src/qml/MenuButton.qml index dbe91f4345..c22d379227 100644 --- a/clients/aurorae/src/qml/MenuButton.qml +++ b/clients/aurorae/src/qml/MenuButton.qml @@ -23,14 +23,14 @@ DecorationButton { id: menuButton buttonType: DecorationOptions.DecorationButtonMenu KQuickControlsAddons.QIconItem { - icon: decoration.icon + icon: decoration.client.icon anchors.fill: parent } Timer { id: timer interval: 150 repeat: false - onTriggered: decoration.menuClicked() + onTriggered: decoration.requestShowWindowMenu() } MouseArea { anchors.fill: parent @@ -64,13 +64,13 @@ DecorationButton { // for right clicks we show the menu instantly // and if the option is disabled we always show menu directly if (!menuButton.closeOnDoubleClick || mouse.button == Qt.RightButton) { - decoration.menuClicked(); + decoration.requestShowWindowMenu(); timer.stop(); } } onDoubleClicked: { if (menuButton.closeOnDoubleClick) { - decoration.closeWindow(); + decoration.requestClose(); } } } diff --git a/clients/aurorae/src/qml/aurorae.qml b/clients/aurorae/src/qml/aurorae.qml index 9c2727957b..b8f9e6c971 100644 --- a/clients/aurorae/src/qml/aurorae.qml +++ b/clients/aurorae/src/qml/aurorae.qml @@ -40,6 +40,16 @@ Decoration { id: options deco: decoration } + Item { + id: titleRect + x: decoration.client.maximized ? maximizedBorders.left : borders.left + y: 0 + width: decoration.client.width//parent.width - x - (decoration.client.maximized ? maximizedBorders.right : borders.right) + height: decoration.client.maximized ? maximizedBorders.top : borders.top + Component.onCompleted: { + decoration.installTitleItem(titleRect); + } + } PlasmaCore.FrameSvg { property bool supportsInactive: hasElementPrefix("decoration-inactive") property bool supportsMaximized: hasElementPrefix("decoration-maximized") @@ -51,12 +61,12 @@ Decoration { } PlasmaCore.FrameSvgItem { id: decorationActive - property bool shown: (!decoration.maxized || !backgroundSvg.supportsMaximized) && (decoration.active || !backgroundSvg.supportsInactive) + property bool shown: (!decoration.client.maxized || !backgroundSvg.supportsMaximized) && (decoration.client.active || !backgroundSvg.supportsInactive) anchors.fill: parent imagePath: backgroundSvg.imagePath prefix: "decoration" opacity: shown ? 1 : 0 - enabledBorders: decoration.maximized ? PlasmaCore.FrameSvg.NoBorder : PlasmaCore.FrameSvg.TopBorder | PlasmaCore.FrameSvg.BottomBorder | PlasmaCore.FrameSvg.LeftBorder | PlasmaCore.FrameSvg.RightBorder + enabledBorders: decoration.client.maximized ? PlasmaCore.FrameSvg.NoBorder : PlasmaCore.FrameSvg.TopBorder | PlasmaCore.FrameSvg.BottomBorder | PlasmaCore.FrameSvg.LeftBorder | PlasmaCore.FrameSvg.RightBorder Behavior on opacity { enabled: root.animate NumberAnimation { @@ -69,8 +79,8 @@ Decoration { anchors.fill: parent imagePath: backgroundSvg.imagePath prefix: "decoration-inactive" - opacity: (!decoration.active && backgroundSvg.supportsInactive) ? 1 : 0 - enabledBorders: decoration.maximized ? PlasmaCore.FrameSvg.NoBorder : PlasmaCore.FrameSvg.TopBorder | PlasmaCore.FrameSvg.BottomBorder | PlasmaCore.FrameSvg.LeftBorder | PlasmaCore.FrameSvg.RightBorder + opacity: (!decoration.client.active && backgroundSvg.supportsInactive) ? 1 : 0 + enabledBorders: decoration.client.maximized ? PlasmaCore.FrameSvg.NoBorder : PlasmaCore.FrameSvg.TopBorder | PlasmaCore.FrameSvg.BottomBorder | PlasmaCore.FrameSvg.LeftBorder | PlasmaCore.FrameSvg.RightBorder Behavior on opacity { enabled: root.animate NumberAnimation { @@ -80,7 +90,7 @@ Decoration { } PlasmaCore.FrameSvgItem { id: decorationMaximized - property bool shown: decoration.maximized && backgroundSvg.supportsMaximized && (decoration.active || !backgroundSvg.supportsMaximizedInactive) + property bool shown: decoration.client.maximized && backgroundSvg.supportsMaximized && (decoration.client.active || !backgroundSvg.supportsMaximizedInactive) anchors { left: parent.left right: parent.right @@ -114,7 +124,7 @@ Decoration { imagePath: backgroundSvg.imagePath prefix: "decoration-maximized-inactive" height: parent.maximizedBorders.top - opacity: (!decoration.active && decoration.maximized && backgroundSvg.supportsMaximizedInactive) ? 1 : 0 + opacity: (!decoration.client.active && decoration.client.maximized && backgroundSvg.supportsMaximizedInactive) ? 1 : 0 enabledBorders: PlasmaCore.FrameSvg.NoBorder Behavior on opacity { enabled: root.animate @@ -130,7 +140,7 @@ Decoration { animate: root.animate anchors { left: root.left - leftMargin: decoration.maximized ? auroraeTheme.titleEdgeLeftMaximized : (auroraeTheme.titleEdgeLeft + root.padding.left) + leftMargin: decoration.client.maximized ? auroraeTheme.titleEdgeLeftMaximized : (auroraeTheme.titleEdgeLeft + root.padding.left) } } AuroraeButtonGroup { @@ -140,40 +150,28 @@ Decoration { animate: root.animate anchors { right: root.right - rightMargin: decoration.maximized ? auroraeTheme.titleEdgeRightMaximized : (auroraeTheme.titleEdgeRight + root.padding.right) + rightMargin: decoration.client.maximized ? auroraeTheme.titleEdgeRightMaximized : (auroraeTheme.titleEdgeRight + root.padding.right) } } Text { id: caption - text: decoration.caption + text: decoration.client.caption textFormat: Text.PlainText horizontalAlignment: auroraeTheme.horizontalAlignment verticalAlignment: auroraeTheme.verticalAlignment elide: Text.ElideRight height: Math.max(auroraeTheme.titleHeight, auroraeTheme.buttonHeight * auroraeTheme.buttonSizeFactor) - color: decoration.active ? auroraeTheme.activeTextColor : auroraeTheme.inactiveTextColor + color: decoration.client.active ? auroraeTheme.activeTextColor : auroraeTheme.inactiveTextColor font: options.titleFont renderType: Text.NativeRendering anchors { left: leftButtonGroup.right right: rightButtonGroup.left top: root.top - topMargin: decoration.maximized ? auroraeTheme.titleEdgeTopMaximized : (auroraeTheme.titleEdgeTop + root.padding.top) + topMargin: decoration.client.maximized ? auroraeTheme.titleEdgeTopMaximized : (auroraeTheme.titleEdgeTop + root.padding.top) leftMargin: auroraeTheme.titleBorderLeft rightMargin: auroraeTheme.titleBorderRight } - MouseArea { - acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton - anchors.fill: parent - onDoubleClicked: decoration.titlebarDblClickOperation() - onPressed: { - if (mouse.button == Qt.LeftButton) { - mouse.accepted = false; - } else { - decoration.titlePressed(mouse.button, mouse.buttons); - } - } - } Behavior on color { enabled: root.animate ColorAnimation { @@ -192,7 +190,7 @@ Decoration { } imagePath: backgroundSvg.imagePath prefix: "innerborder" - opacity: (decoration.active && !decoration.maximized && backgroundSvg.supportsInnerBorder) ? 1 : 0 + opacity: (decoration.client.active && !decoration.client.maximized && backgroundSvg.supportsInnerBorder) ? 1 : 0 Behavior on opacity { enabled: root.animate NumberAnimation { @@ -211,7 +209,7 @@ Decoration { } imagePath: backgroundSvg.imagePath prefix: "innerborder-inactive" - opacity: (!decoration.active && !decoration.maximized && backgroundSvg.supportsInnerBorderInactive) ? 1 : 0 + opacity: (!decoration.client.active && !decoration.client.maximized && backgroundSvg.supportsInnerBorderInactive) ? 1 : 0 Behavior on opacity { enabled: root.animate NumberAnimation { diff --git a/clients/aurorae/themes/plastik/code/plastikbutton.cpp b/clients/aurorae/themes/plastik/code/plastikbutton.cpp index 6ad55a68e3..3e42964b29 100644 --- a/clients/aurorae/themes/plastik/code/plastikbutton.cpp +++ b/clients/aurorae/themes/plastik/code/plastikbutton.cpp @@ -21,6 +21,8 @@ along with this program. If not, see . #include "plastikbutton.h" #include #include +#include +#include #include namespace KWin @@ -118,7 +120,8 @@ QPixmap PlastikButtonProvider::icon(ButtonIcon icon, int size, bool active, bool QPixmap image(size, size); image.fill(Qt::transparent); QPainter p(&image); - const QColor color = KDecoration::options()->color(KDecoration::ColorFont, active); + KConfigGroup wmConfig(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("WM")); + const QColor color = wmConfig.readEntry("activeForeground", QPalette().color(QPalette::Active, QPalette::HighlightedText)); if (shadow) { p.setPen(KColorScheme::shade(color, KColorScheme::ShadowShade)); diff --git a/clients/aurorae/themes/plastik/package/contents/ui/PlastikButton.qml b/clients/aurorae/themes/plastik/package/contents/ui/PlastikButton.qml index f22f17e46b..a290379839 100644 --- a/clients/aurorae/themes/plastik/package/contents/ui/PlastikButton.qml +++ b/clients/aurorae/themes/plastik/package/contents/ui/PlastikButton.qml @@ -24,7 +24,7 @@ DecorationButton { var highlightColor = null; if (button.pressed) { if (button.buttonType == DecorationOptions.DecorationButtonClose) { - highlightColor = colorHelper.foreground(decoration.active, ColorHelper.NegativeText); + highlightColor = colorHelper.foreground(decoration.client.active, ColorHelper.NegativeText); } else { highlightColor = options.titleBarColor; } @@ -32,7 +32,7 @@ DecorationButton { highlightColor = colorHelper.multiplyAlpha(highlightColor, 0.3); } else if (button.hovered) { if (button.buttonType == DecorationOptions.DecorationButtonClose) { - highlightColor = colorHelper.foreground(decoration.active, ColorHelper.NegativeText); + highlightColor = colorHelper.foreground(decoration.client.active, ColorHelper.NegativeText); } else { highlightColor = options.titleBarColor; } @@ -114,7 +114,7 @@ DecorationButton { Item { property int imageWidth: button.width > 14 ? button.width - 2 * Math.floor(button.width/3.5) : button.width - 6 property int imageHeight: button.height > 14 ? button.height - 2 * Math.floor(button.height/3.5) : button.height - 6 - property string source: "image://plastik/" + button.buttonType + "/" + decoration.active + "/" + ((buttonType == "A") ? decoration.maximized : button.toggled) + property string source: "image://plastik/" + button.buttonType + "/" + decoration.client.active + "/" + ((buttonType == "A") ? decoration.client.maximized : button.toggled) anchors.fill: parent Image { id: shadowImage @@ -141,22 +141,18 @@ DecorationButton { Component.onCompleted: { colorize(); if (buttonType == DecorationOptions.DecorationButtonQuickHelp) { - visible = decoration.providesContextHelp; + visible = Qt.binding(function() { return decoration.client.providesContextHelp}); } if (buttonType == DecorationOptions.DecorationButtonApplicationMenu) { - visible = decoration.appMenu; +// visible = decoration.appMenu; + visible = false; } } onHoveredChanged: colorize() onPressedChanged: colorize() Connections { - target: decoration + target: decoration.client onActiveChanged: button.colorize() - onAppMenuChanged: { - if (buttonType == DecorationOptions.DecorationButtonApplicationMenu) { - visible = decoration.appMenu; - } - } } Connections { target: options diff --git a/clients/aurorae/themes/plastik/package/contents/ui/main.qml b/clients/aurorae/themes/plastik/package/contents/ui/main.qml index 11c58be2f0..269f37c58c 100644 --- a/clients/aurorae/themes/plastik/package/contents/ui/main.qml +++ b/clients/aurorae/themes/plastik/package/contents/ui/main.qml @@ -107,7 +107,7 @@ Decoration { fill: parent } border { - width: decoration.maximized ? 0 : 2 + width: decoration.client.maximized ? 0 : 2 color: colorHelper.shade(root.titleBarColor, ColorHelper.DarkShade) } Rectangle { @@ -120,7 +120,7 @@ Decoration { bottomMargin: 1 topMargin: 1 } - visible: !decoration.maximized + visible: !decoration.client.maximized width: root.borders.left color: root.titleBarColor Rectangle { @@ -130,7 +130,7 @@ Decoration { top: parent.top bottom: parent.bottom } - color: colorHelper.shade(root.titleBarColor, ColorHelper.LightShade, colorHelper.contrast - (decoration.active ? 0.4 : 0.8)) + color: colorHelper.shade(root.titleBarColor, ColorHelper.LightShade, colorHelper.contrast - (decoration.client.active ? 0.4 : 0.8)) } } Rectangle { @@ -143,7 +143,7 @@ Decoration { bottomMargin: 1 topMargin: 1 } - visible: !decoration.maximzied + visible: !decoration.client.maximzied width: root.borders.right -1 color: root.titleBarColor Rectangle { @@ -153,7 +153,7 @@ Decoration { top: parent.top } x: parent.x + parent.width - 1 - color: colorHelper.shade(root.titleBarColor, ColorHelper.DarkShade, colorHelper.contrast - (decoration.active ? 0.4 : 0.8)) + color: colorHelper.shade(root.titleBarColor, ColorHelper.DarkShade, colorHelper.contrast - (decoration.client.active ? 0.4 : 0.8)) } } Rectangle { @@ -166,7 +166,7 @@ Decoration { rightMargin: 1 } height: root.borders.bottom - visible: !decoration.maximzied + visible: !decoration.client.maximzied color: root.titleBarColor Rectangle { height: 1 @@ -175,7 +175,7 @@ Decoration { right: parent.right } y: parent.y + parent.height - 1 - color: colorHelper.shade(root.titleBarColor, ColorHelper.DarkShade, colorHelper.contrast - (decoration.active ? 0.4 : 0.8)) + color: colorHelper.shade(root.titleBarColor, ColorHelper.DarkShade, colorHelper.contrast - (decoration.client.active ? 0.4 : 0.8)) } } @@ -184,14 +184,14 @@ Decoration { property int topMargin: 1 property real normalHeight: titleRow.normalHeight + topMargin + 1 property real maximizedHeight: titleRow.maximizedHeight + 1 - height: decoration.maximized ? maximizedHeight : normalHeight + height: decoration.client.maximized ? maximizedHeight : normalHeight anchors { left: parent.left right: parent.right top: parent.top - topMargin: decoration.maximized ? 0 : top.topMargin - leftMargin: decoration.maximized ? 0 : 2 - rightMargin: decoration.maximized ? 0 : 2 + topMargin: decoration.client.maximized ? 0 : top.topMargin + leftMargin: decoration.client.maximized ? 0 : 2 + rightMargin: decoration.client.maximized ? 0 : 2 } gradient: Gradient { id: topGradient @@ -201,7 +201,7 @@ Decoration { } GradientStop { id: middleGradientStop - position: 4.0/(decoration.maximized ? top.maximizedHeight : top.normalHeight) + position: 4.0/(decoration.client.maximized ? top.maximizedHeight : top.normalHeight) color: colorHelper.shade(root.titleBarColor, ColorHelper.MidShade, colorHelper.contrast - 0.4) } GradientStop { @@ -216,21 +216,8 @@ Decoration { left: top.left right: top.right } - visible: !decoration.maximized - color: colorHelper.shade(root.titleBarColor, ColorHelper.LightShade, colorHelper.contrast - (decoration.active ? 0.4 : 0.8)) - } - MouseArea { - acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton - anchors.fill: parent - onDoubleClicked: decoration.titlebarDblClickOperation() - onPressed: { - if (mouse.button == Qt.LeftButton) { - mouse.accepted = false; - } else { - decoration.titlePressed(mouse.button, mouse.buttons); - } - } - onReleased: decoration.titleReleased(mouse.button, mouse.buttons) + visible: !decoration.client.maximized + color: colorHelper.shade(root.titleBarColor, ColorHelper.LightShade, colorHelper.contrast - (decoration.client.active ? 0.4 : 0.8)) } Item { @@ -244,9 +231,9 @@ Decoration { left: parent.left right: parent.right top: parent.top - topMargin: decoration.maximized ? 0 : titleRow.topMargin - leftMargin: decoration.maximized ? 0 : 3 - rightMargin: decoration.maximized ? 0 : 3 + topMargin: decoration.client.maximized ? 0 : titleRow.topMargin + leftMargin: decoration.client.maximized ? 0 : 3 + rightMargin: decoration.client.maximized ? 0 : 3 bottomMargin: titleRow.bottomMargin } ButtonGroup { @@ -284,7 +271,7 @@ Decoration { Behavior on color { ColorAnimation { duration: root.animationDuration } } - text: decoration.caption + text: decoration.client.caption font: options.titleFont style: root.titleShadow ? Text.Raised : Text.Normal styleColor: colorHelper.shade(color, ColorHelper.ShadowShade) @@ -311,6 +298,9 @@ Decoration { right: parent.right } } + Component.onCompleted: { + decoration.installTitleItem(titleRow); + } } } @@ -325,7 +315,7 @@ Decoration { } height: 1 y: top.height - 1 - visible: decoration.maximized + visible: decoration.client.maximized color: colorHelper.shade(root.titleBarColor, ColorHelper.MidShade) } @@ -341,7 +331,7 @@ Decoration { width: 1 color: colorHelper.shade(root.titleBarColor, ColorHelper.MidShade) } - visible: !decoration.maximized + visible: !decoration.client.maximized color: root.titleBarColor } } @@ -423,8 +413,4 @@ Decoration { maximizedBorders.setTitle(top.maximizedHeight); readConfig(); } - Connections { - target: decoration - onConfigChanged: readConfig() - } }