hyprland/ipc: expose active and focused properties + activate()
This commit is contained in:
parent
207e6114a3
commit
62ccab5d30
7 changed files with 92 additions and 33 deletions
|
@ -314,7 +314,7 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
|
|||
delete workspace;
|
||||
|
||||
for (auto* monitor: this->mMonitors.valueList()) {
|
||||
if (monitor->activeWorkspace() == nullptr) {
|
||||
if (monitor->bindableActiveWorkspace().value() == nullptr) {
|
||||
// removing a monitor will cause a new workspace to be created and destroyed after removal,
|
||||
// but it won't go back to a real workspace afterwards and just leaves a null, so we
|
||||
// re-query monitors if this appears to be the case.
|
||||
|
@ -342,11 +342,11 @@ void HyprlandIpc::onEvent(HyprlandIpcEvent* event) {
|
|||
auto id = args.at(0).toInt();
|
||||
auto name = QString::fromUtf8(args.at(1));
|
||||
|
||||
if (this->mFocusedMonitor != nullptr) {
|
||||
if (this->bFocusedMonitor != nullptr) {
|
||||
auto* workspace = this->findWorkspaceByName(name, true, id);
|
||||
this->mFocusedMonitor->setActiveWorkspace(workspace);
|
||||
this->bFocusedMonitor->setActiveWorkspace(workspace);
|
||||
qCDebug(logHyprlandIpc) << "Workspace" << id << "activated on"
|
||||
<< this->mFocusedMonitor->bindableName().value();
|
||||
<< this->bFocusedMonitor->bindableName().value();
|
||||
}
|
||||
} else if (event->name == "moveworkspacev2") {
|
||||
auto args = event->parseView(3);
|
||||
|
@ -504,8 +504,6 @@ HyprlandIpc::findMonitorByName(const QString& name, bool createIfMissing, qint32
|
|||
}
|
||||
}
|
||||
|
||||
HyprlandMonitor* HyprlandIpc::focusedMonitor() const { return this->mFocusedMonitor; }
|
||||
|
||||
HyprlandMonitor* HyprlandIpc::monitorFor(QuickshellScreenInfo* screen) {
|
||||
// Wayland monitors appear after hyprland ones are created and disappear after destruction
|
||||
// so simply not doing any preemptive creation is enough, however if this call creates
|
||||
|
@ -517,22 +515,22 @@ HyprlandMonitor* HyprlandIpc::monitorFor(QuickshellScreenInfo* screen) {
|
|||
}
|
||||
|
||||
void HyprlandIpc::setFocusedMonitor(HyprlandMonitor* monitor) {
|
||||
if (monitor == this->mFocusedMonitor) return;
|
||||
auto* oldMonitor = this->bFocusedMonitor.value();
|
||||
if (monitor == oldMonitor) return;
|
||||
|
||||
if (this->mFocusedMonitor != nullptr) {
|
||||
QObject::disconnect(this->mFocusedMonitor, nullptr, this, nullptr);
|
||||
if (this->bFocusedMonitor != nullptr) {
|
||||
QObject::disconnect(this->bFocusedMonitor, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mFocusedMonitor = monitor;
|
||||
|
||||
if (monitor != nullptr) {
|
||||
QObject::connect(monitor, &QObject::destroyed, this, &HyprlandIpc::onFocusedMonitorDestroyed);
|
||||
}
|
||||
emit this->focusedMonitorChanged();
|
||||
|
||||
this->bFocusedMonitor = monitor;
|
||||
}
|
||||
|
||||
void HyprlandIpc::onFocusedMonitorDestroyed() {
|
||||
this->mFocusedMonitor = nullptr;
|
||||
this->bFocusedMonitor = nullptr;
|
||||
emit this->focusedMonitorChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
#include <qhash.h>
|
||||
#include <qlocalsocket.h>
|
||||
#include <qobject.h>
|
||||
#include <qproperty.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../../../core/model.hpp"
|
||||
#include "../../../core/qmlscreen.hpp"
|
||||
|
@ -74,7 +76,11 @@ public:
|
|||
void dispatch(const QString& request);
|
||||
|
||||
[[nodiscard]] HyprlandMonitor* monitorFor(QuickshellScreenInfo* screen);
|
||||
[[nodiscard]] HyprlandMonitor* focusedMonitor() const;
|
||||
|
||||
[[nodiscard]] QBindable<HyprlandMonitor*> bindableFocusedMonitor() const {
|
||||
return &this->bFocusedMonitor;
|
||||
}
|
||||
|
||||
void setFocusedMonitor(HyprlandMonitor* monitor);
|
||||
|
||||
[[nodiscard]] ObjectModel<HyprlandMonitor>* monitors();
|
||||
|
@ -119,10 +125,15 @@ private:
|
|||
|
||||
ObjectModel<HyprlandMonitor> mMonitors {this};
|
||||
ObjectModel<HyprlandWorkspace> mWorkspaces {this};
|
||||
HyprlandMonitor* mFocusedMonitor = nullptr;
|
||||
//HyprlandWorkspace* activeWorkspace = nullptr;
|
||||
|
||||
HyprlandIpcEvent event {this};
|
||||
|
||||
Q_OBJECT_BINDABLE_PROPERTY(
|
||||
HyprlandIpc,
|
||||
HyprlandMonitor*,
|
||||
bFocusedMonitor,
|
||||
&HyprlandIpc::focusedMonitorChanged
|
||||
);
|
||||
};
|
||||
|
||||
} // namespace qs::hyprland::ipc
|
||||
|
|
|
@ -18,6 +18,11 @@ void HyprlandMonitor::updateInitial(qint32 id, const QString& name, const QStrin
|
|||
this->bId = id;
|
||||
this->bName = name;
|
||||
this->bDescription = description;
|
||||
|
||||
this->bFocused.setBinding([this]() {
|
||||
return HyprlandIpc::instance()->bindableFocusedMonitor().value() == this;
|
||||
});
|
||||
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
|
@ -38,8 +43,8 @@ void HyprlandMonitor::updateFromObject(QVariantMap object) {
|
|||
this->bScale = object.value("scale").value<qreal>();
|
||||
Qt::endPropertyUpdateGroup();
|
||||
|
||||
if (this->mActiveWorkspace == nullptr
|
||||
|| this->mActiveWorkspace->bindableName().value() != activeWorkspaceName)
|
||||
if (this->bActiveWorkspace == nullptr
|
||||
|| this->bActiveWorkspace->bindableName().value() != activeWorkspaceName)
|
||||
{
|
||||
auto* workspace = this->ipc->findWorkspaceByName(activeWorkspaceName, true, activeWorkspaceId);
|
||||
workspace->setMonitor(this);
|
||||
|
@ -54,16 +59,15 @@ void HyprlandMonitor::updateFromObject(QVariantMap object) {
|
|||
}
|
||||
}
|
||||
|
||||
HyprlandWorkspace* HyprlandMonitor::activeWorkspace() const { return this->mActiveWorkspace; }
|
||||
|
||||
void HyprlandMonitor::setActiveWorkspace(HyprlandWorkspace* workspace) {
|
||||
if (workspace == this->mActiveWorkspace) return;
|
||||
auto* oldWorkspace = this->bActiveWorkspace.value();
|
||||
if (workspace == oldWorkspace) return;
|
||||
|
||||
if (this->mActiveWorkspace != nullptr) {
|
||||
QObject::disconnect(this->mActiveWorkspace, nullptr, this, nullptr);
|
||||
if (oldWorkspace != nullptr) {
|
||||
QObject::disconnect(oldWorkspace, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mActiveWorkspace = workspace;
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
|
||||
if (workspace != nullptr) {
|
||||
workspace->setMonitor(this);
|
||||
|
@ -76,12 +80,11 @@ void HyprlandMonitor::setActiveWorkspace(HyprlandWorkspace* workspace) {
|
|||
);
|
||||
}
|
||||
|
||||
emit this->activeWorkspaceChanged();
|
||||
this->bActiveWorkspace = workspace;
|
||||
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
void HyprlandMonitor::onActiveWorkspaceDestroyed() {
|
||||
this->mActiveWorkspace = nullptr;
|
||||
emit this->activeWorkspaceChanged();
|
||||
}
|
||||
void HyprlandMonitor::onActiveWorkspaceDestroyed() { this->bActiveWorkspace = nullptr; }
|
||||
|
||||
} // namespace qs::hyprland::ipc
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <qtypes.h>
|
||||
|
||||
#include "connection.hpp"
|
||||
#include "workspace.hpp"
|
||||
|
||||
namespace qs::hyprland::ipc {
|
||||
|
||||
|
@ -30,7 +31,9 @@ class HyprlandMonitor: public QObject {
|
|||
/// > property, run @@Hyprland.refreshMonitors() and wait for this property to update.
|
||||
Q_PROPERTY(QVariantMap lastIpcObject READ lastIpcObject NOTIFY lastIpcObjectChanged);
|
||||
/// The currently active workspace on this monitor. May be null.
|
||||
Q_PROPERTY(qs::hyprland::ipc::HyprlandWorkspace* activeWorkspace READ activeWorkspace NOTIFY activeWorkspaceChanged);
|
||||
Q_PROPERTY(qs::hyprland::ipc::HyprlandWorkspace* activeWorkspace READ default NOTIFY activeWorkspaceChanged);
|
||||
/// If the monitor is currently focused.
|
||||
Q_PROPERTY(bool focused READ default NOTIFY focusedChanged);
|
||||
// clang-format on
|
||||
QML_ELEMENT;
|
||||
QML_UNCREATABLE("HyprlandMonitors must be retrieved from the HyprlandIpc object.");
|
||||
|
@ -50,10 +53,15 @@ public:
|
|||
[[nodiscard]] QBindable<qint32> bindableHeight() { return &this->bHeight; }
|
||||
[[nodiscard]] QBindable<qreal> bindableScale() { return &this->bScale; }
|
||||
|
||||
[[nodiscard]] QBindable<HyprlandWorkspace*> bindableActiveWorkspace() const {
|
||||
return &this->bActiveWorkspace;
|
||||
}
|
||||
|
||||
[[nodiscard]] QBindable<bool> bindableFocused() const { return &this->bFocused; }
|
||||
|
||||
[[nodiscard]] QVariantMap lastIpcObject() const;
|
||||
|
||||
void setActiveWorkspace(HyprlandWorkspace* workspace);
|
||||
[[nodiscard]] HyprlandWorkspace* activeWorkspace() const;
|
||||
|
||||
signals:
|
||||
void idChanged();
|
||||
|
@ -66,6 +74,7 @@ signals:
|
|||
void scaleChanged();
|
||||
void lastIpcObjectChanged();
|
||||
void activeWorkspaceChanged();
|
||||
void focusedChanged();
|
||||
|
||||
private slots:
|
||||
void onActiveWorkspaceDestroyed();
|
||||
|
@ -74,7 +83,6 @@ private:
|
|||
HyprlandIpc* ipc;
|
||||
|
||||
QVariantMap mLastIpcObject;
|
||||
HyprlandWorkspace* mActiveWorkspace = nullptr;
|
||||
|
||||
// clang-format off
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(HyprlandMonitor, qint32, bId, -1, &HyprlandMonitor::idChanged);
|
||||
|
@ -85,6 +93,8 @@ private:
|
|||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qint32, bWidth, &HyprlandMonitor::widthChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qint32, bHeight, &HyprlandMonitor::heightChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, qreal, bScale, &HyprlandMonitor::scaleChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, HyprlandWorkspace*, bActiveWorkspace, &HyprlandMonitor::activeWorkspaceChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandMonitor, bool, bFocused, &HyprlandMonitor::focusedChanged);
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ QString HyprlandIpcQml::requestSocketPath() { return HyprlandIpc::instance()->re
|
|||
QString HyprlandIpcQml::eventSocketPath() { return HyprlandIpc::instance()->eventSocketPath(); }
|
||||
|
||||
HyprlandMonitor* HyprlandIpcQml::focusedMonitor() {
|
||||
return HyprlandIpc::instance()->focusedMonitor();
|
||||
return HyprlandIpc::instance()->bindableFocusedMonitor().value();
|
||||
}
|
||||
|
||||
ObjectModel<HyprlandMonitor>* HyprlandIpcQml::monitors() {
|
||||
|
|
|
@ -59,10 +59,24 @@ void HyprlandWorkspace::setMonitor(HyprlandMonitor* monitor) {
|
|||
|
||||
this->mMonitor = monitor;
|
||||
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
|
||||
if (monitor != nullptr) {
|
||||
QObject::connect(monitor, &QObject::destroyed, this, &HyprlandWorkspace::onMonitorDestroyed);
|
||||
|
||||
this->bActive.setBinding([this]() {
|
||||
return this->mMonitor->bindableActiveWorkspace().value() == this;
|
||||
});
|
||||
|
||||
this->bFocused.setBinding([this]() {
|
||||
return this->bActive.value() && this->mMonitor->bindableFocused().value();
|
||||
});
|
||||
} else {
|
||||
this->bActive = false;
|
||||
this->bFocused = false;
|
||||
}
|
||||
|
||||
Qt::endPropertyUpdateGroup();
|
||||
emit this->monitorChanged();
|
||||
}
|
||||
|
||||
|
@ -71,4 +85,8 @@ void HyprlandWorkspace::onMonitorDestroyed() {
|
|||
emit this->monitorChanged();
|
||||
}
|
||||
|
||||
void HyprlandWorkspace::activate() {
|
||||
HyprlandIpc::instance()->dispatch(QString("workspace %1").arg(this->bId.value()));
|
||||
}
|
||||
|
||||
} // namespace qs::hyprland::ipc
|
||||
|
|
|
@ -16,6 +16,11 @@ class HyprlandWorkspace: public QObject {
|
|||
Q_OBJECT;
|
||||
Q_PROPERTY(qint32 id READ default NOTIFY idChanged BINDABLE bindableId);
|
||||
Q_PROPERTY(QString name READ default NOTIFY nameChanged BINDABLE bindableName);
|
||||
/// If this workspace is currently active on its monitor. See also @@focused.
|
||||
Q_PROPERTY(bool active READ default NOTIFY activeChanged BINDABLE bindableActive);
|
||||
/// If this workspace is currently active on a monitor and that monitor is currently
|
||||
/// focused. See also @@active.
|
||||
Q_PROPERTY(bool focused READ default NOTIFY focusedChanged BINDABLE bindableFocused);
|
||||
/// Last json returned for this workspace, as a javascript object.
|
||||
///
|
||||
/// > [!WARNING] This is *not* updated unless the workspace object is fetched again from
|
||||
|
@ -32,8 +37,18 @@ public:
|
|||
void updateInitial(qint32 id, const QString& name);
|
||||
void updateFromObject(QVariantMap object);
|
||||
|
||||
/// Activate the workspace.
|
||||
///
|
||||
/// > [!NOTE] This is equivalent to running
|
||||
/// > ```qml
|
||||
/// > HyprlandIpc.dispatch(`workspace ${workspace.id}`);
|
||||
/// > ```
|
||||
Q_INVOKABLE void activate();
|
||||
|
||||
[[nodiscard]] QBindable<qint32> bindableId() { return &this->bId; }
|
||||
[[nodiscard]] QBindable<QString> bindableName() { return &this->bName; }
|
||||
[[nodiscard]] QBindable<bool> bindableActive() { return &this->bActive; }
|
||||
[[nodiscard]] QBindable<bool> bindableFocused() { return &this->bFocused; }
|
||||
|
||||
[[nodiscard]] QVariantMap lastIpcObject() const;
|
||||
|
||||
|
@ -43,6 +58,8 @@ public:
|
|||
signals:
|
||||
void idChanged();
|
||||
void nameChanged();
|
||||
void activeChanged();
|
||||
void focusedChanged();
|
||||
void lastIpcObjectChanged();
|
||||
void monitorChanged();
|
||||
|
||||
|
@ -58,6 +75,8 @@ private:
|
|||
// clang-format off
|
||||
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(HyprlandWorkspace, qint32, bId, -1, &HyprlandWorkspace::idChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandWorkspace, QString, bName, &HyprlandWorkspace::nameChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandWorkspace, bool, bActive, &HyprlandWorkspace::activeChanged);
|
||||
Q_OBJECT_BINDABLE_PROPERTY(HyprlandWorkspace, bool, bFocused, &HyprlandWorkspace::focusedChanged);
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue