diff --git a/clients/aurorae/src/CMakeLists.txt b/clients/aurorae/src/CMakeLists.txt index 2a3754cfa7..cee7f85397 100644 --- a/clients/aurorae/src/CMakeLists.txt +++ b/clients/aurorae/src/CMakeLists.txt @@ -3,9 +3,6 @@ include_directories( ./lib ) set(kwin3_aurorae_PART_SRCS aurorae.cpp - lib/auroraebutton.cpp - lib/auroraescene.cpp - lib/auroraetab.cpp lib/auroraetheme.cpp lib/themeconfig.cpp ) @@ -20,3 +17,11 @@ install(TARGETS kwin3_aurorae DESTINATION ${PLUGIN_INSTALL_DIR} ) install( FILES aurorae.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin ) install( FILES aurorae.knsrc DESTINATION ${CONFIG_INSTALL_DIR} ) +install( FILES + qml/aurorae.qml + qml/AuroraeButton.qml + qml/AuroraeButtonGroup.qml + qml/Decoration.qml + qml/DecorationButton.qml + qml/MenuButton.qml + DESTINATION ${DATA_INSTALL_DIR}/kwin/aurorae ) diff --git a/clients/aurorae/src/aurorae.cpp b/clients/aurorae/src/aurorae.cpp index 5bb24f8469..8fbf96d3b5 100644 --- a/clients/aurorae/src/aurorae.cpp +++ b/clients/aurorae/src/aurorae.cpp @@ -16,17 +16,16 @@ along with this program. If not, see . *********************************************************************/ #include "aurorae.h" -#include "auroraescene.h" #include "auroraetheme.h" #include -#include -#include -#include #include +#include +#include #include #include +#include #include namespace Aurorae @@ -135,46 +134,15 @@ AuroraeFactory *AuroraeFactory::s_instance = NULL; *******************************************************/ AuroraeClient::AuroraeClient(KDecorationBridge *bridge, KDecorationFactory *factory) : KDecorationUnstable(bridge, factory) - , m_clickInProgress(false) { - m_scene = new AuroraeScene(AuroraeFactory::instance()->theme(), - options()->customButtonPositions() ? options()->titleButtonsLeft() : AuroraeFactory::instance()->theme()->defaultButtonsLeft(), - options()->customButtonPositions() ? options()->titleButtonsRight() : AuroraeFactory::instance()->theme()->defaultButtonsRight(), - providesContextHelp(), NULL); - connect(m_scene, SIGNAL(closeWindow()), SLOT(closeWindow()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(maximize(Qt::MouseButtons)), SLOT(maximize(Qt::MouseButtons)), Qt::QueuedConnection); - connect(m_scene, SIGNAL(showContextHelp()), SLOT(showContextHelp()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(minimizeWindow()), SLOT(minimize()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(menuClicked()), SLOT(menuClicked()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(menuDblClicked()), SLOT(closeWindow()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(toggleOnAllDesktops()), SLOT(toggleOnAllDesktops()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(toggleShade()), SLOT(toggleShade()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(toggleKeepAbove()), SLOT(toggleKeepAbove()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(toggleKeepBelow()), SLOT(toggleKeepBelow()), Qt::QueuedConnection); - connect(m_scene, SIGNAL(titlePressed(Qt::MouseButton,Qt::MouseButtons)), - SLOT(titlePressed(Qt::MouseButton,Qt::MouseButtons))); - connect(m_scene, SIGNAL(titleReleased(Qt::MouseButton,Qt::MouseButtons)), - SLOT(titleReleased(Qt::MouseButton,Qt::MouseButtons))); - connect(m_scene, SIGNAL(titleDoubleClicked()), SLOT(titlebarDblClickOperation())); - connect(m_scene, SIGNAL(titleMouseMoved(Qt::MouseButton,Qt::MouseButtons)), - SLOT(titleMouseMoved(Qt::MouseButton,Qt::MouseButtons))); - connect(m_scene, SIGNAL(wheelEvent(int)), SLOT(titlebarMouseWheelOperation(int))); - connect(m_scene, SIGNAL(tabMouseButtonPress(QGraphicsSceneMouseEvent*,int)), - SLOT(tabMouseButtonPress(QGraphicsSceneMouseEvent*,int))); - connect(m_scene, SIGNAL(tabMouseButtonRelease(QGraphicsSceneMouseEvent*,int)), - SLOT(tabMouseButtonRelease(QGraphicsSceneMouseEvent*,int))); - connect(m_scene, SIGNAL(tabRemoved(int)), SLOT(tabRemoved(int))); - connect(m_scene, SIGNAL(tabMoved(int,int)), SLOT(tabMoved(int,int))); - connect(m_scene, SIGNAL(tabMovedToGroup(long int,int)), SLOT(tabMovedToGroup(long int,int))); - connect(this, SIGNAL(keepAboveChanged(bool)), SLOT(slotKeepAboveChanged(bool))); - connect(this, SIGNAL(keepBelowChanged(bool)), SLOT(slotKeepBelowChanged(bool))); + connect(this, SIGNAL(keepAboveChanged(bool)), SIGNAL(keepAboveChangedWrapper())); + connect(this, SIGNAL(keepBelowChanged(bool)), SIGNAL(keepBelowChangedWrapper())); } AuroraeClient::~AuroraeClient() { m_view->setParent(NULL); m_view->deleteLater(); - m_scene->deleteLater(); } void AuroraeClient::init() @@ -187,7 +155,6 @@ void AuroraeClient::init() createMainWidget(); widget()->setAttribute(Qt::WA_TranslucentBackground); widget()->setAttribute(Qt::WA_NoSystemBackground); - widget()->installEventFilter(this); m_view = new QDeclarativeView(widget()); m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView); m_view->setAttribute(Qt::WA_TranslucentBackground); @@ -198,58 +165,46 @@ void AuroraeClient::init() QPalette pal2 = widget()->palette(); pal2.setColor(widget()->backgroundRole(), Qt::transparent); widget()->setPalette(pal2); + + // setup the QML engine + foreach (const QString &importPath, KGlobal::dirs()->findDirs("module", "imports")) { + m_view->engine()->addImportPath(importPath); + } m_view->rootContext()->setContextProperty("decoration", this); - // scene initialisation - m_scene->setActive(isActive(), false); - m_scene->setIcon(icon()); - m_scene->setAllDesktops(isOnAllDesktops()); - m_scene->setMaximizeMode(options()->moveResizeMaximizedWindows() ? MaximizeRestore : maximizeMode()); - m_scene->setShade(isShade()); - m_scene->setKeepAbove(keepAbove()); - m_scene->setKeepBelow(keepBelow()); - m_scene->setFont(KDecoration::options()->font(true), true); - m_scene->setFont(KDecoration::options()->font(false), false); + m_view->rootContext()->setContextProperty("auroraeTheme", AuroraeFactory::instance()->theme()); + m_view->setSource(QUrl(KStandardDirs::locate("data", "kwin/aurorae/aurorae.qml"))); AuroraeFactory::instance()->theme()->setCompositingActive(compositingActive()); } void AuroraeClient::activeChange() { - if (m_scene->isActive() != isActive()) { - m_scene->setActive(isActive()); - } emit activeChanged(); } void AuroraeClient::captionChange() { - checkTabs(true); emit captionChanged(); } void AuroraeClient::iconChange() { - m_scene->setIcon(icon()); emit iconChanged(); } void AuroraeClient::desktopChange() { - m_scene->setAllDesktops(isOnAllDesktops()); emit desktopChanged(); } void AuroraeClient::maximizeChange() { if (!options()->moveResizeMaximizedWindows()) { - m_scene->setMaximizeMode(maximizeMode()); + emit maximizeChanged(); } - emit maximizeChanged(); } void AuroraeClient::resize(const QSize &s) { - m_scene->setSceneRect(QRectF(QPoint(0, 0), s)); - m_scene->updateLayout(); m_view->resize(s); widget()->resize(s); updateWindowShape(); @@ -257,19 +212,31 @@ void AuroraeClient::resize(const QSize &s) void AuroraeClient::shadeChange() { - m_scene->setShade(isShade()); emit shadeChanged(); } void AuroraeClient::borders(int &left, int &right, int &top, int &bottom) const { const bool maximized = maximizeMode() == MaximizeFull && !options()->moveResizeMaximizedWindows(); - AuroraeFactory::instance()->theme()->borders(left, top, right, bottom, maximized); + if (maximized) { + left = m_view->rootObject()->property("borderLeftMaximized").toInt(); + right = m_view->rootObject()->property("borderRightMaximized").toInt(); + top = m_view->rootObject()->property("borderTopMaximized").toInt(); + bottom = m_view->rootObject()->property("borderBottomMaximized").toInt(); + } else { + left = m_view->rootObject()->property("borderLeft").toInt(); + right = m_view->rootObject()->property("borderRight").toInt(); + top = m_view->rootObject()->property("borderTop").toInt(); + bottom = m_view->rootObject()->property("borderBottom").toInt(); + } } void AuroraeClient::padding(int &left, int &right, int &top, int &bottom) const { - AuroraeFactory::instance()->theme()->padding(left, top, right, bottom); + left = m_view->rootObject()->property("paddingLeft").toInt(); + right = m_view->rootObject()->property("paddingRight").toInt(); + top = m_view->rootObject()->property("paddingTop").toInt(); + bottom = m_view->rootObject()->property("paddingBottom").toInt(); } QSize AuroraeClient::minimumSize() const @@ -330,12 +297,10 @@ void AuroraeClient::reset(long unsigned int changed) AuroraeFactory::instance()->theme()->setCompositingActive(compositingActive()); } if (changed & SettingButtons) { - m_scene->setButtons(options()->customButtonPositions() ? options()->titleButtonsLeft() : AuroraeFactory::instance()->theme()->defaultButtonsLeft(), - options()->customButtonPositions() ? options()->titleButtonsRight() : AuroraeFactory::instance()->theme()->defaultButtonsRight()); + // TODO: update buttons } if (changed & SettingFont) { - m_scene->setFont(KDecoration::options()->font(true), true); - m_scene->setFont(KDecoration::options()->font(false), false); + // TODO: set font } KDecoration::reset(changed); } @@ -350,22 +315,6 @@ void AuroraeClient::toggleShade() setShade(!isShade()); } -void AuroraeClient::slotKeepAboveChanged(bool above) -{ - if (above && m_scene->isKeepBelow()) { - m_scene->setKeepBelow(false); - } - m_scene->setKeepAbove(above); -} - -void AuroraeClient::slotKeepBelowChanged(bool below) -{ - if (below && m_scene->isKeepAbove()) { - m_scene->setKeepAbove(false); - } - m_scene->setKeepBelow(below); -} - void AuroraeClient::toggleKeepAbove() { setKeepAbove(!keepAbove()); @@ -447,72 +396,6 @@ void AuroraeClient::titleMouseMoved(Qt::MouseButton button, Qt::MouseButtons but event = 0; } -void AuroraeClient::checkTabs(bool force) -{ - if (m_scene->tabCount() == 1 && clientGroupItems().count() == 1 && !force) { - return; - } - while (m_scene->tabCount() < clientGroupItems().count()) { - m_scene->addTab(QString()); - } - while (m_scene->tabCount() > clientGroupItems().count()) { - m_scene->removeLastTab(); - } - QList data; - foreach (const ClientGroupItem &item, clientGroupItems()) { - data << AuroraeTabData(item.title(), item.icon()); - } - m_scene->setAllTabData(data); - m_scene->setFocusedTab(visibleClientGroupItem()); -} - -bool AuroraeClient::eventFilter(QObject *o, QEvent *e) -{ - if (o != widget()) { - return false; - } - if (e->type() == QEvent::Paint) { - checkTabs(); - } - return false; -} - -void AuroraeClient::tabMouseButtonPress(QGraphicsSceneMouseEvent *e, int index) -{ - if (buttonToWindowOperation(e->buttons()) == OperationsOp) { - displayClientMenu(index, e->screenPos()); - return; - } else if (buttonToWindowOperation(e->buttons()) == ClientGroupDragOp) { - m_scene->setUniqueTabDragId(index, itemId(index)); - } - titlePressed(e->button(), e->buttons()); - m_clickInProgress = true; -} - -void AuroraeClient::tabMouseButtonRelease(QGraphicsSceneMouseEvent *e, int index) -{ - if (m_clickInProgress) { - setVisibleClientGroupItem(index); - } - titleReleased(e->button(), e->buttons()); - m_clickInProgress = false; -} - -void AuroraeClient::tabRemoved(int index) -{ - removeFromClientGroup(index); -} - -void AuroraeClient::tabMoved(int index, int before) -{ - moveItemInClientGroup(index, before); -} - -void AuroraeClient::tabMovedToGroup(long int uid, int before) -{ - moveItemToClientGroup(uid, before); -} - QString AuroraeClient::rightButtons() const { // TODO: make independent of Aurorae diff --git a/clients/aurorae/src/aurorae.h b/clients/aurorae/src/aurorae.h index 993505bbda..9052ba0e50 100644 --- a/clients/aurorae/src/aurorae.h +++ b/clients/aurorae/src/aurorae.h @@ -30,7 +30,6 @@ class QGraphicsScene; namespace Aurorae { class AuroraeTheme; -class AuroraeScene; class AuroraeFactory : public QObject, public KDecorationFactoryUnstable { @@ -77,8 +76,8 @@ class AuroraeClient : public KDecorationUnstable Q_PROPERTY(bool setShade READ isSetShade NOTIFY shadeChanged) Q_PROPERTY(bool shade READ isShade WRITE setShade NOTIFY shadeChanged) Q_PROPERTY(bool shadeable READ isShadeable) - Q_PROPERTY(bool keepAbove READ keepAbove WRITE setKeepAbove NOTIFY keepAboveChanged) - Q_PROPERTY(bool keepBelow READ keepBelow WRITE setKeepBelow NOTIFY keepBelowChanged) + Q_PROPERTY(bool keepAbove READ keepAbove WRITE setKeepAbove NOTIFY keepAboveChangedWrapper) + Q_PROPERTY(bool keepBelow READ keepBelow WRITE setKeepBelow NOTIFY keepBelowChangedWrapper) // TODO: maximize mode Q_PROPERTY(bool providesContextHelp READ providesContextHelp) Q_PROPERTY(QRect transparentRect READ transparentRect) @@ -114,14 +113,12 @@ Q_SIGNALS: void iconChanged(); void maximizeChanged(); void shadeChanged(); - void keepAboveChanged(); - void keepBelowChanged(); + void keepAboveChangedWrapper(); + void keepBelowChangedWrapper(); public slots: void menuClicked(); void toggleShade(); - void slotKeepAboveChanged(bool above); - void slotKeepBelowChanged(bool below); void toggleKeepAbove(); void toggleKeepBelow(); void titlePressed(int button, int buttons); @@ -130,21 +127,10 @@ public slots: void titlePressed(Qt::MouseButton button, Qt::MouseButtons buttons); void titleReleased(Qt::MouseButton button, Qt::MouseButtons buttons); void titleMouseMoved(Qt::MouseButton button, Qt::MouseButtons buttons); - void tabMouseButtonPress(QGraphicsSceneMouseEvent *e, int index); - void tabMouseButtonRelease(QGraphicsSceneMouseEvent *e, int index); - void tabRemoved(int index); - void tabMoved(int index, int before); - void tabMovedToGroup(long int uid, int before); - -protected: - virtual bool eventFilter(QObject *o, QEvent *e); private: void updateWindowShape(); - void checkTabs(bool force = false); - AuroraeScene *m_scene; QDeclarativeView *m_view; - bool m_clickInProgress; }; } diff --git a/clients/aurorae/src/qml/AuroraeButton.qml b/clients/aurorae/src/qml/AuroraeButton.qml new file mode 100644 index 0000000000..190d4b12b9 --- /dev/null +++ b/clients/aurorae/src/qml/AuroraeButton.qml @@ -0,0 +1,329 @@ +/******************************************************************** +Copyright (C) 2012 Martin Gräßlin + +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) any later version. + +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 . +*********************************************************************/ +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +DecorationButton { + function widthForButton() { + switch (buttonType) { + case "M": + // menu + return auroraeTheme.buttonWidthMenu; + case "S": + // all desktops + return auroraeTheme.buttonWidthAllDesktops; + case "H": + // help + return auroraeTheme.buttonWidthHelp; + case "I": + // minimize + return auroraeTheme.buttonWidthMinimize; + case "A": + // maximize + return auroraeTheme.buttonWidthMaximizeRestore; + case "X": + // close + return auroraeTheme.buttonWidthClose; + case "F": + // keep above + return auroraeTheme.buttonWidthKeepAbove; + case "B": + // keep below + return auroraeTheme.buttonWidthKeepBelow; + case "L": + // shade + return auroraeTheme.buttonWidthShade; + default: + return auroraeTheme.buttonWidth; + } + } + function pathForButton() { + switch (buttonType) { + case "S": + // all desktops + return auroraeTheme.allDesktopsButtonPath; + case "H": + // help + return auroraeTheme.helpButtonPath; + case "I": + // minimize + return auroraeTheme.minimizeButtonPath; + case "A": + // maximize + return auroraeTheme.maximizeButtonPath; + case "X": + // close + return auroraeTheme.closeButtonPath; + case "F": + // keep above + return auroraeTheme.keepAboveButtonPath; + case "B": + // keep below + return auroraeTheme.keepBelowButtonPath; + case "L": + // shade + return auroraeTheme.shadeButtonPath; + default: + return ""; + } + } + function toggledPressedStatusChange() { + if (pressed || toggled) { + // pressed comes after hovered (if supported) + if (!decoration.active && buttonSvg.supportsInactivePressed) { + // if inactive and the buttons supports pressed, we use it + // in case we have an inactive-hover but no pressed we stay in hovered state + state = "inactive-pressed"; + } else if (decoration.active && state != "inactive-hover" && buttonSvg.supportsPressed) { + state = "active-pressed"; + } + } else { + if (!decoration.active && hovered && buttonSvg.supportsInactiveHover) { + state = "inactive-hover"; + } else if (!decoration.active && buttonSvg.supportsInactive) { + state = "inactive"; + } else if (hovered && buttonSvg.supportsHover) { + state = "active-hover"; + } else { + state = "active"; + } + } + } + width: widthForButton() * auroraeTheme.buttonSizeFactor + height: auroraeTheme.buttonHeight * auroraeTheme.buttonSizeFactor + PlasmaCore.FrameSvg { + property bool supportsHover: hasElementPrefix("hover") + property bool supportsPressed: hasElementPrefix("pressed") + property bool supportsDeactivated: hasElementPrefix("deactivated") + property bool supportsInactive: hasElementPrefix("inactive") + property bool supportsInactiveHover: hasElementPrefix("hover-inactive") + property bool supportsInactivePressed: hasElementPrefix("pressed-inactive") + property bool supportsInactiveDeactivated: hasElementPrefix("deactivated-inactive") + id: buttonSvg + imagePath: pathForButton() + } + PlasmaCore.FrameSvgItem { + id: buttonActive + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "active" + } + PlasmaCore.FrameSvgItem { + id: buttonActiveHover + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "hover" + opacity: 0 + } + PlasmaCore.FrameSvgItem { + id: buttonActivePressed + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "pressed" + opacity: 0 + } + PlasmaCore.FrameSvgItem { + id: buttonActiveDeactivated + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "deactivated" + opacity: 0 + } + PlasmaCore.FrameSvgItem { + id: buttonInactive + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "inactive" + opacity: 0 + } + PlasmaCore.FrameSvgItem { + id: buttonInactiveHover + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "hover-inactive" + opacity: 0 + } + PlasmaCore.FrameSvgItem { + id: buttonInactivePressed + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "pressed-inactive" + opacity: 0 + } + PlasmaCore.FrameSvgItem { + id: buttonInactiveDeactivated + anchors.fill: parent + imagePath: buttonSvg.imagePath + prefix: "deactivated-inactive" + opacity: 0 + } + Component.onCompleted: { + if (!decoration.active && !enabled && buttonSvg.supportsInactiveDeactivated) { + state = "inactive-deactivated"; + } else if (!enabled && buttonSvg.supportsDeactivated) { + state = "active-deactivated"; + } else if (!decoration.active && (toggled || pressed) && buttonSvg.supportsInactivePressed) { + state = "inactive-pressed"; + } else if ((toggled || pressed) && buttonSvg.supportsPressed) { + state = "active-pressed"; + } else if (!decoration.active && buttonSvg.supportsInactive) { + state = "inactive"; + } else { + state = "active"; + } + if (buttonType == "H" && !decoration.providesContextHelp) { + visible = false; + } else { + visible = buttonSvg.imagePath != ""; + } + } + onHoveredChanged: { + if (state == "active-pressed" || state == "inactive-pressed") { + // state change of hovered does not matter as the button is currently pressed + return; + } + if (hovered) { + if (state == "active" && buttonSvg.supportsHover) { + state = "active-hover"; + } else if (state == "inactive" && buttonSvg.supportsInactiveHover) { + state = "inactive-hover"; + } + } else { + if (!decoration.active && buttonSvg.supportsInactive) { + state = "inactive"; + } else { + state = "active"; + } + } + } + onPressedChanged: toggledPressedStatusChange() + onToggledChanged: toggledPressedStatusChange() + states: [ + State { name: "active" }, + State { name: "active-hover" }, + State { name: "active-pressed" }, + State { name: "active-deactivated" }, + State { name: "inactive" }, + State { name: "inactive-hover" }, + State { name: "inactive-pressed" }, + State { name: "inactive-deactivated" } + ] + transitions: [ + Transition { + to: "active" + // Cross fade from somewhere to active + ParallelAnimation { + NumberAnimation { target: buttonActive; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "active-hover" + // Cross fade from active to hover + ParallelAnimation { + NumberAnimation { target: buttonActive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActiveHover; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "active-pressed" + // Cross fade to pressed state + ParallelAnimation { + NumberAnimation { target: buttonActive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActivePressed; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "inactive" + // Cross fade from hover/pressed/active to inactive + ParallelAnimation { + NumberAnimation { target: buttonActive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactive; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "inactive-hover" + // Cross fade from inactive to hover + ParallelAnimation { + NumberAnimation { target: buttonActiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveHover; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "inactive-pressed" + // Cross fade to inactive pressed state + ParallelAnimation { + NumberAnimation { target: buttonActivePressed; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveHover; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactivePressed; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "active-deactivated" + ParallelAnimation { + NumberAnimation { target: buttonActive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActiveDeactivated; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveDeactivated; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "inactive-deactivated" + ParallelAnimation { + NumberAnimation { target: buttonActive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonActiveDeactivated; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: buttonInactiveDeactivated; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + } + } + ] + Connections { + target: decoration + onActiveChanged: { + if (!decoration.active && !enabled && buttonSvg.supportsInactiveDeactivated) { + state = "inactive-deactivated"; + } else if (!enabled && buttonSvg.supportsDeactivated) { + state = "active-deactivated"; + } else if (!decoration.active && (pressed || toggled) && buttonSvg.supportsInactivePressed) { + state = "inactive-pressed"; + } else if (!decoration.active && hovered && buttonSvg.supportsInactiveHover) { + state = "inactive-hover"; + } else if (!decoration.active && buttonSvg.supportsInactive) { + state = "inactive"; + } else if ((pressed || toggled) && buttonSvg.supportsPressed) { + state = "active-pressed"; + } else if (hovered && buttonSvg.supportsHover) { + state = "active-hover"; + } else { + state = "active"; + } + } + } +} diff --git a/clients/aurorae/src/qml/AuroraeButtonGroup.qml b/clients/aurorae/src/qml/AuroraeButtonGroup.qml new file mode 100644 index 0000000000..ee92139d8b --- /dev/null +++ b/clients/aurorae/src/qml/AuroraeButtonGroup.qml @@ -0,0 +1,42 @@ +/******************************************************************** +Copyright (C) 2012 Martin Gräßlin + +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) any later version. + +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 . +*********************************************************************/ +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: group + property string buttons + + Component.onCompleted: { + var component = Qt.createComponent("AuroraeButton.qml"); + for (var i=0; i + +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) any later version. + +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 . +*********************************************************************/ +import QtQuick 1.1 + +Item { + property int paddingLeft + property int paddingRight + property int paddingTop + property int paddingBottom + property int borderLeft + property int borderRight + property int borderTop + property int borderBottom + property int borderLeftMaximized + property int borderRightMaximized + property int borderTopMaximized + property int borderBottomMaximized + MouseArea { + anchors.fill: parent + hoverEnabled: true + onPositionChanged: decoration.titleMouseMoved(mouse.button, mouse.buttons) + } +} diff --git a/clients/aurorae/src/qml/DecorationButton.qml b/clients/aurorae/src/qml/DecorationButton.qml new file mode 100644 index 0000000000..f857986f83 --- /dev/null +++ b/clients/aurorae/src/qml/DecorationButton.qml @@ -0,0 +1,147 @@ +/******************************************************************** +Copyright (C) 2012 Martin Gräßlin + +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) any later version. + +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 . +*********************************************************************/ +import QtQuick 1.1 + +Item { + id: button + property string buttonType : "" + property bool hovered: false + property bool pressed: false + property bool toggled: false + enabled: { + switch (button.buttonType) { + case "X": + return decoration.closeable; + case "A": + return decoration.maximizeable; + case "I": + return decoration.minimizeable; + case "_": + return false; + default: + return true; + } + } + MouseArea { + anchors.fill: parent + acceptedButtons: { + switch (button.buttonType) { + case "M": + return Qt.LeftButton | Qt.RightButton; + case "A": + return Qt.LeftButton | Qt.RightButton | Qt.MiddleButton; + default: + return Qt.LeftButton; + } + } + hoverEnabled: true + onEntered: button.hovered = true + onPositionChanged: decoration.titleMouseMoved(mouse.button, mouse.buttons) + onExited: button.hovered = false + onPressed: button.pressed = true + onReleased: button.pressed = false + onClicked: { + switch (button.buttonType) { + case "M": + // menu + decoration.menuClicked(); + break; + case "S": + // all desktops + decoration.toggleOnAllDesktops(); + break; + case "H": + // help + decoration.showContextHelp(); + break; + case "I": + // minimize + decoration.minimize(); + break; + case "A": + // maximize + decoration.maximize(mouse.buttons); + break; + case "X": + // close + decoration.closeWindow(); + break; + case "F": + // keep above + decoration.toggleKeepAbove(); + break; + case "B": + // keep below + decoration.toggleKeepBelow(); + break; + case "L": + // shade + decoration.toggleShade(); + break; + } + } + onDoubleClicked: { + if (button.buttonType == "M") { + decoration.closeWindow(); + } + } + Component.onCompleted: { + switch (button.buttonType) { + case "S": + // all desktops + button.toggled = decoration.onAllDesktops; + break; + case "F": + button.toggled = decoration.keepAbove; + break; + case "B": + button.toggled = decoration.keepBelow; + break; + case "L": + button.toggled = decoration.shade; + break; + } + } + Connections { + target: decoration + onShadeChanged: { + if (button.buttonType != "L") { + return; + } + button.toggled = decoration.shade; + } + onKeepBelowChanged: { + if (button.buttonType != "B") { + return; + } + button.toggled = decoration.keepBelow; + } + onKeepAboveChanged: { + if (button.buttonType != "F") { + return; + } + button.toggled = decoration.keepAbove; + } + onDesktopChanged: { + if (button.buttonType != "S") { + return; + } + button.toggled = decoration.onAllDesktops; + } + } + } +} diff --git a/clients/aurorae/src/qml/MenuButton.qml b/clients/aurorae/src/qml/MenuButton.qml new file mode 100644 index 0000000000..186df8111e --- /dev/null +++ b/clients/aurorae/src/qml/MenuButton.qml @@ -0,0 +1,26 @@ +/******************************************************************** +Copyright (C) 2012 Martin Gräßlin + +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) any later version. + +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 . +*********************************************************************/ +import QtQuick 1.1 +import org.kde.qtextracomponents 0.1 as QtExtra + +DecorationButton { + buttonType: "M" + QtExtra.QIconItem { + icon: decoration.icon + anchors.fill: parent + } +} diff --git a/clients/aurorae/src/qml/aurorae.qml b/clients/aurorae/src/qml/aurorae.qml new file mode 100644 index 0000000000..131d9f607b --- /dev/null +++ b/clients/aurorae/src/qml/aurorae.qml @@ -0,0 +1,143 @@ +/******************************************************************** +Copyright (C) 2012 Martin Gräßlin + +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) any later version. + +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 . +*********************************************************************/ +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Decoration { + id: root + borderLeft: auroraeTheme.borderLeft + borderRight: auroraeTheme.borderRight + borderTop: auroraeTheme.borderTop + borderBottom: auroraeTheme.borderBottom + borderLeftMaximized: auroraeTheme.borderLeftMaximized + borderRightMaximized: auroraeTheme.borderRightMaximized + borderBottomMaximized: auroraeTheme.borderBottomMaximized + borderTopMaximized: auroraeTheme.borderTopMaximized + paddingLeft: auroraeTheme.paddingLeft + paddingRight: auroraeTheme.paddingRight + paddingBottom: auroraeTheme.paddingBottom + paddingTop: auroraeTheme.paddingTop + Component.onCompleted: { + if (decoration.active) { + root.state = "active"; + } else { + if (backgroundSvg.supportsInactive) { + root.state = "inactive"; + } else { + root.state = "active"; + } + } + } + PlasmaCore.FrameSvg { + property bool supportsInactive: hasElementPrefix("decoration-inactive") + id: backgroundSvg + imagePath: auroraeTheme.decorationPath + } + PlasmaCore.FrameSvgItem { + id: decorationActive + anchors.fill: parent + imagePath: backgroundSvg.imagePath + prefix: "decoration" + } + PlasmaCore.FrameSvgItem { + id: decorationInactive + anchors.fill: parent + imagePath: backgroundSvg.imagePath + prefix: "decoration-inactive" + opacity: 0 + } + AuroraeButtonGroup { + id: leftButtonGroup + buttons: decoration.leftButtons + width: childrenRect.width + anchors { + top: parent.top + left: parent.left + leftMargin: auroraeTheme.titleEdgeLeft + root.paddingLeft + topMargin: root.paddingTop + auroraeTheme.titleEdgeTop + auroraeTheme.buttonMarginTop + } + } + AuroraeButtonGroup { + id: rightButtonGroup + buttons: decoration.rightButtons + width: childrenRect.width + anchors { + top: parent.top + right: parent.right + rightMargin: auroraeTheme.titleEdgeRight + root.paddingRight + topMargin: root.paddingTop + auroraeTheme.titleEdgeTop + auroraeTheme.buttonMarginTop + } + } + Text { + id: caption + text: decoration.caption + horizontalAlignment: auroraeTheme.horizontalAlignment + verticalAlignment: auroraeTheme.verticalAlignment + elide: Text.ElideRight + anchors { + left: leftButtonGroup.right + right: rightButtonGroup.left + top: root.top + topMargin: root.paddingTop + auroraeTheme.titleEdgeTop + leftMargin: auroraeTheme.titleBorderLeft + rightMargin: auroraeTheme.titleBorderRight + } + MouseArea { + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton + anchors.fill: parent + onDoubleClicked: decoration.titlebarDblClickOperation() + onPressed: decoration.titlePressed(mouse.button, mouse.buttons) + onReleased: decoration.titleReleased(mouse.button, mouse.buttons) + } + } + states: [ + State { name: "active" }, + State { name: "inactive" } + ] + transitions: [ + Transition { + to: "active" + // Cross fade from inactive to active + ParallelAnimation { + NumberAnimation { target: decorationActive; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + NumberAnimation { target: decorationInactive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + ColorAnimation { target: caption; property: "color"; to: auroraeTheme.activeTextColor; duration: auroraeTheme.animationTime } + } + }, + Transition { + to: "inactive" + // Cross fade from active to inactive + ParallelAnimation { + NumberAnimation { target: decorationActive; property: "opacity"; to: 0; duration: auroraeTheme.animationTime } + NumberAnimation { target: decorationInactive; property: "opacity"; to: 1; duration: auroraeTheme.animationTime } + ColorAnimation { target: caption; property: "color"; to: auroraeTheme.inactiveTextColor; duration: auroraeTheme.animationTime } + } + } + ] + Connections { + target: decoration + onActiveChanged: { + if (decoration.active) { + root.state = "active"; + } else { + if (backgroundSvg.supportsInactive) { + root.state = "inactive"; + } + } + } + } +}