Make it possible to move windows between screens if there's more than one

This commit is contained in:
Aleix Pol 2021-08-31 02:02:17 +02:00 committed by Aleix Pol Gonzalez
parent 1de0f3ec58
commit 4aa1bc3a8c
3 changed files with 118 additions and 0 deletions

View file

@ -7,6 +7,8 @@
import QtQuick 2.0
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import QtQuick.Controls 2.2 as QQC2
import org.kde.plasma.phone.taskpanel 1.0
import org.kde.taskmanager 0.1 as TaskManager
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents
@ -17,7 +19,9 @@ Item {
height: window.height/2
//Workaround
required property var model
property bool active: model.IsActive
readonly property point taskScreenPoint: Qt.point(model.ScreenGeometry.x, model.ScreenGeometry.y)
onActiveChanged: {
//sometimes the task switcher window itself appears, screwing up the state
if (model.IsActive) {
@ -128,6 +132,20 @@ Item {
text: model.AppName
color: PlasmaCore.Theme.textColor
}
Repeater {
id: rep
model: plasmoid.nativeInterface.outputs
delegate: PlasmaComponents.ToolButton {
text: model.modelName
visible: model.position !== delegate.taskScreenPoint
display: rep.count < 3 ? QQC2.Button.IconOnly : QQC2.Button.TextBesideIcon
icon.name: "tv" //TODO provide a more adequate icon
onClicked: {
plasmoid.nativeInterface.sendWindowToOutput(delegate.model.WinIdList[0], model.output)
}
}
}
PlasmaComponents.ToolButton {
z: 99
icon.name: "window-close"

View file

@ -12,6 +12,7 @@
#include <QtQml>
#include <KWayland/Client/connection_thread.h>
#include <KWayland/Client/output.h>
#include <KWayland/Client/plasmashell.h>
#include <KWayland/Client/plasmawindowmanagement.h>
#include <KWayland/Client/registry.h>
@ -23,6 +24,76 @@
static const QString s_kwinService = QStringLiteral("org.kde.KWin");
constexpr int ACTIVE_WINDOW_UPDATE_INVERVAL = 250;
class OutputsModel : public QAbstractListModel
{
public:
enum Roles {
Model = Qt::DisplayRole,
Geometry = Qt::UserRole,
Position,
Output,
};
OutputsModel(QObject *parent)
: QAbstractListModel(parent)
{
}
QHash<int, QByteArray> roleNames() const override
{
return {
{Model, "modelName"},
{Geometry, "geometry"},
{Position, "position"},
{Output, "output"},
};
}
void createOutput(wl_output *output)
{
auto newOutput = new KWayland::Client::Output(this);
connect(newOutput, &KWayland::Client::Output::removed, this, [this, newOutput] {
auto i = m_outputs.indexOf(newOutput);
Q_ASSERT(i >= 0);
beginRemoveRows({}, i, i);
m_outputs.removeAt(i);
endRemoveRows();
});
newOutput->setup(output);
beginInsertRows({}, m_outputs.count(), m_outputs.count());
m_outputs.append(newOutput);
endInsertRows();
}
int rowCount(const QModelIndex &parent) const override
{
return parent.isValid() ? 0 : m_outputs.count();
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
{
if (index.row() >= m_outputs.count()) {
return {};
}
auto o = m_outputs[index.row()];
switch (role) {
case Model:
return o->model();
case Geometry:
return o->geometry();
case Position:
return o->globalPosition();
case Output:
return QVariant::fromValue<QObject *>(o);
}
return {};
}
private:
QVector<KWayland::Client::Output *> m_outputs;
};
// helper class to expose the NOTIFY in the properties
class KwinVirtualKeyboardInterface : public OrgKdeKwinVirtualKeyboardInterface
{
@ -41,6 +112,7 @@ TaskPanel::TaskPanel(QObject *parent, const QVariantList &args)
: Plasma::Containment(parent, args)
, m_showingDesktop(false)
, m_windowManagement(nullptr)
, m_outputsModel(new OutputsModel(this))
{
setHasConfigurationInterface(true);
m_activeTimer = new QTimer(this);
@ -49,6 +121,8 @@ TaskPanel::TaskPanel(QObject *parent, const QVariantList &args)
connect(m_activeTimer, &QTimer::timeout, this, &TaskPanel::updateActiveWindow);
initWayland();
qmlRegisterUncreatableType<KWayland::Client::Output>("org.kde.plasma.phone.taskpanel", 1, 0, "Output", "nope");
qmlRegisterUncreatableType<OutputsModel>("org.kde.plasma.phone.taskpanel", 1, 0, "OutputsModel", "nope");
qmlRegisterSingletonType<OrgKdeKwinVirtualKeyboardInterface>("org.kde.plasma.phone.taskpanel",
1,
0,
@ -87,6 +161,9 @@ void TaskPanel::initWayland()
}
auto *registry = new Registry(this);
registry->create(connection);
connect(registry, &Registry::outputAnnounced, m_outputsModel, [this, registry](quint32 name, quint32 version) {
m_outputsModel->createOutput(registry->bindOutput(name, version));
});
connect(registry, &Registry::plasmaWindowManagementAnnounced, this, [this, registry](quint32 name, quint32 version) {
m_windowManagement = registry->createPlasmaWindowManagement(name, version, this);
qRegisterMetaType<QVector<int>>("QVector<int>");
@ -213,6 +290,21 @@ void TaskPanel::closeActiveWindow()
}
}
void TaskPanel::sendWindowToOutput(const QString &uuid, KWayland::Client::Output *output)
{
const auto windows = m_windowManagement->windows();
for (auto w : windows) {
if (w->uuid() == uuid) {
w->sendToOutput(output);
}
}
}
QAbstractItemModel *TaskPanel::outputs() const
{
return m_outputsModel;
}
K_PLUGIN_CLASS_WITH_JSON(TaskPanel, "metadata.json")
#include "taskpanel.moc"

View file

@ -9,12 +9,14 @@
#include <Plasma/Containment>
class OutputsModel;
class QAbstractItemModel;
namespace KWayland
{
namespace Client
{
class Output;
class PlasmaWindowManagement;
class PlasmaWindow;
class PlasmaShell;
@ -31,6 +33,7 @@ class TaskPanel : public Plasma::Containment
Q_PROPERTY(bool hasCloseableActiveWindow READ hasCloseableActiveWindow NOTIFY hasCloseableActiveWindowChanged)
Q_PROPERTY(QWindow *panel READ panel WRITE setPanel NOTIFY panelChanged)
Q_PROPERTY(Plasma::Types::Location location READ location WRITE setLocation NOTIFY locationChanged)
Q_PROPERTY(QAbstractItemModel *outputs READ outputs CONSTANT)
public:
TaskPanel(QObject *parent, const QVariantList &args);
@ -53,6 +56,10 @@ public:
}
bool hasCloseableActiveWindow() const;
QAbstractItemModel *outputs() const;
Q_INVOKABLE void sendWindowToOutput(const QString &uuid, KWayland::Client::Output *output);
public Q_SLOTS:
void forgetActiveWindow();
@ -76,6 +83,7 @@ private:
KWayland::Client::PlasmaWindowManagement *m_windowManagement = nullptr;
QPointer<KWayland::Client::PlasmaWindow> m_activeWindow;
QTimer *m_activeTimer;
OutputsModel *m_outputsModel;
};
#endif