diff --git a/containments/taskpanel/CMakeLists.txt b/containments/taskpanel/CMakeLists.txt index 761e907a..499ce34a 100644 --- a/containments/taskpanel/CMakeLists.txt +++ b/containments/taskpanel/CMakeLists.txt @@ -1,2 +1,24 @@ +set(taskpanel_SRCS + taskpanel.cpp +) + +add_library(plasma_containment_phone_taskpanel MODULE ${taskpanel_SRCS}) + +kcoreaddons_desktop_to_json(plasma_containment_phone_taskpanel package/metadata.desktop) + +target_link_libraries(plasma_containment_phone_taskpanel + Qt5::Gui + Qt5::DBus + KF5::Plasma + Qt5::Qml + Qt5::Quick + KF5::I18n + KF5::Service + KF5::WaylandClient + ) + + +install(TARGETS plasma_containment_phone_taskpanel DESTINATION ${KDE_INSTALL_PLUGINDIR}/plasma/applets) + plasma_install_package(package org.kde.phone.taskpanel) diff --git a/containments/taskpanel/package/contents/ui/TaskSwitcher.qml b/containments/taskpanel/package/contents/ui/TaskSwitcher.qml index bfabf61b..7cfa80b0 100644 --- a/containments/taskpanel/package/contents/ui/TaskSwitcher.qml +++ b/containments/taskpanel/package/contents/ui/TaskSwitcher.qml @@ -38,6 +38,8 @@ FullScreenPanel { property int currentTaskIndex: -1 property alias model: tasksModel + Component.onCompleted: plasmoid.nativeInterface.panel = window; + color: Qt.rgba(0, 0, 0, 0.8 * Math.min( (Math.min(tasksView.contentY + tasksView.height, tasksView.height) / tasksView.height), ((tasksView.contentHeight - tasksView.contentY - tasksView.headerItem.height - tasksView.footerItem.height)/tasksView.height))) @@ -53,7 +55,7 @@ FullScreenPanel { scrollAnim.from = tasksView.contentY; scrollAnim.to = 0; scrollAnim.running = true; - setSingleActiveWindow(-1); + plasmoid.nativeInterface.requestShowingDesktop(true); } function hide() { scrollAnim.from = tasksView.contentY; @@ -66,16 +68,8 @@ FullScreenPanel { } function setSingleActiveWindow(id) { - var task; - for (var i = 0; i < tasksModel.count; ++i) { - task = filterModel.get(i); - - if (i == id) { - tasksModel.requestActivate(tasksModel.index(i, 0)); - currentTaskIndex = id; - } else if (i != id && !task.IsMinimized) { - tasksModel.requestToggleMinimized(tasksModel.index(i, 0)); - } + if (id >= 0) { + tasksModel.requestActivate(tasksModel.index(id, 0)); } } @@ -206,7 +200,7 @@ FullScreenPanel { iconSource: "go-home" onClicked: { currentTaskIndex = -1; - setSingleActiveWindow(-1); + plasmoid.nativeInterface.requestShowingDesktop(true); window.hide(); } } diff --git a/containments/taskpanel/package/contents/ui/main.qml b/containments/taskpanel/package/contents/ui/main.qml index 7a3862ed..5f29ab76 100644 --- a/containments/taskpanel/package/contents/ui/main.qml +++ b/containments/taskpanel/package/contents/ui/main.qml @@ -69,7 +69,7 @@ PlasmaCore.ColorScope { if (taskSwitcher.visibility == Window.Hidden && taskSwitcher.offset > -taskSwitcher.height + units.gridUnit && taskSwitcher.tasksCount) { taskSwitcher.visible = true; } - taskSwitcher.setSingleActiveWindow(-1); + plasmoid.nativeInterface.requestShowingDesktop(true); } onReleased: { if (!isDragging) { diff --git a/containments/taskpanel/taskpanel.cpp b/containments/taskpanel/taskpanel.cpp new file mode 100644 index 00000000..9b2b0bfc --- /dev/null +++ b/containments/taskpanel/taskpanel.cpp @@ -0,0 +1,177 @@ +/*************************************************************************** + * Copyright (C) 2015 Marco Martin * + * * + * 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#include "taskpanel.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +static const QString s_kwinService = QStringLiteral("org.kde.KWin"); + +TaskPanel::TaskPanel(QObject *parent, const QVariantList &args) + : Plasma::Containment(parent, args) + , m_showingDesktop(false) + , m_windowManagement(nullptr) +{ + setHasConfigurationInterface(true); + initWayland(); +} + +TaskPanel::~TaskPanel() +{ +} + +void TaskPanel::requestShowingDesktop(bool showingDesktop) +{ + if (!m_windowManagement) { + return; + } + m_windowManagement->setShowingDesktop(showingDesktop); +} + +void TaskPanel::initWayland() +{ + if (!QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) { + return; + } + using namespace KWayland::Client; + ConnectionThread *connection = ConnectionThread::fromApplication(this); + if (!connection) { + return; + } + Registry *registry = new Registry(this); + registry->create(connection); + connect(registry, &Registry::plasmaWindowManagementAnnounced, this, + [this, registry] (quint32 name, quint32 version) { + m_windowManagement = registry->createPlasmaWindowManagement(name, version, this); + qRegisterMetaType >("QVector"); + connect(m_windowManagement, &PlasmaWindowManagement::showingDesktopChanged, this, + [this] (bool showing) { + if (showing == m_showingDesktop) { + return; + } + m_showingDesktop = showing; + emit showingDesktopChanged(m_showingDesktop); + } + ); + connect(m_windowManagement, &PlasmaWindowManagement::activeWindowChanged, this, &TaskPanel::updateActiveWindow); + updateActiveWindow(); + } + ); + connect(registry, &Registry::plasmaShellAnnounced, this, + [this, registry] (quint32 name, quint32 version) { + + m_shellInterface = registry->createPlasmaShell(name, version, this); + + if (!m_panel) { + return; + } + Surface *s = Surface::fromWindow(m_panel); + if (!s) { + return; + } + m_shellSurface = m_shellInterface->createSurface(s, this); + } + ); + registry->setup(); +} + +QWindow *TaskPanel::panel() +{ + return m_panel; +} + +void TaskPanel::setPanel(QWindow *panel) +{ + using namespace KWayland::Client; + if (panel == m_panel) { + return; + } + + m_panel = panel; + emit panelChanged(); + + if (!m_shellSurface) { + return; + } + Surface *s = Surface::fromWindow(panel); + if (!s) { + return; + } + + m_shellSurface = m_shellInterface->createSurface(s, this); +} + +void TaskPanel::updateActiveWindow() +{ + if (!m_windowManagement) { + return; + } + if (m_activeWindow) { + disconnect(m_activeWindow.data(), &KWayland::Client::PlasmaWindow::closeableChanged, this, &TaskPanel::hasCloseableActiveWindowChanged); + disconnect(m_activeWindow.data(), &KWayland::Client::PlasmaWindow::unmapped, + this, &TaskPanel::forgetActiveWindow); + } + m_activeWindow = m_windowManagement->activeWindow(); + + connect(m_activeWindow.data(), &KWayland::Client::PlasmaWindow::closeableChanged, this, &TaskPanel::hasCloseableActiveWindowChanged); + connect(m_activeWindow.data(), &KWayland::Client::PlasmaWindow::unmapped, + this, &TaskPanel::forgetActiveWindow); + + // TODO: connect to closeableChanged, not needed right now as KWin doesn't provide this changeable + emit hasCloseableActiveWindowChanged(); +} + +bool TaskPanel::hasCloseableActiveWindow() const +{ + return m_activeWindow && m_activeWindow->isCloseable() && !m_activeWindow->isMinimized(); +} + +void TaskPanel::forgetActiveWindow() +{ + if (m_activeWindow) { + disconnect(m_activeWindow.data(), &KWayland::Client::PlasmaWindow::closeableChanged, this, &TaskPanel::hasCloseableActiveWindowChanged); + disconnect(m_activeWindow.data(), &KWayland::Client::PlasmaWindow::unmapped, + this, &TaskPanel::forgetActiveWindow); + } + m_activeWindow.clear(); + emit hasCloseableActiveWindowChanged(); +} + +void TaskPanel::closeActiveWindow() +{ + if (m_activeWindow) { + m_activeWindow->requestClose(); + } +} + +K_EXPORT_PLASMA_APPLET_WITH_JSON(taskpanel, TaskPanel, "metadata.json") + +#include "taskpanel.moc" diff --git a/containments/taskpanel/taskpanel.h b/containments/taskpanel/taskpanel.h new file mode 100644 index 00000000..911535a7 --- /dev/null +++ b/containments/taskpanel/taskpanel.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2015 Marco Martin * + * + * * + * 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, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + +#ifndef TASKPANEL_H +#define TASKPANEL_H + +#include + +class QAbstractItemModel; + +namespace KWayland +{ +namespace Client +{ +class PlasmaWindowManagement; +class PlasmaWindow; +class PlasmaWindowModel; +class PlasmaShell; +class PlasmaShellSurface; +class Surface; +} +} + +class TaskPanel : public Plasma::Containment +{ + Q_OBJECT + Q_PROPERTY(bool showDesktop READ isShowingDesktop WRITE requestShowingDesktop NOTIFY showingDesktopChanged) + Q_PROPERTY(bool hasCloseableActiveWindow READ hasCloseableActiveWindow NOTIFY hasCloseableActiveWindowChanged) + Q_PROPERTY(QWindow *panel READ panel WRITE setPanel NOTIFY panelChanged) + +public: + TaskPanel( QObject *parent, const QVariantList &args ); + ~TaskPanel(); + + QWindow *panel(); + void setPanel(QWindow *panel); + + Q_INVOKABLE void closeActiveWindow(); + + bool isShowingDesktop() const { + return m_showingDesktop; + } + void requestShowingDesktop(bool showingDesktop); + + bool hasCloseableActiveWindow() const; + +public Q_SLOTS: + void forgetActiveWindow(); + +Q_SIGNALS: + void showingDesktopChanged(bool); + void hasCloseableActiveWindowChanged(); + void panelChanged(); + +private: + void initWayland(); + void updateActiveWindow(); + bool m_showingDesktop; + QWindow *m_panel = nullptr; + KWayland::Client::PlasmaShellSurface *m_shellSurface = nullptr; + KWayland::Client::Surface *m_surface = nullptr; + KWayland::Client::PlasmaShell *m_shellInterface = nullptr; + KWayland::Client::PlasmaWindowManagement *m_windowManagement = nullptr; + KWayland::Client::PlasmaWindowModel *m_windowModel = nullptr; + QPointer m_activeWindow; +}; + +#endif