forked from quickshell/quickshell
hyprland/ipc: expose Hyprland toplevels
This commit is contained in:
parent
c115df8d34
commit
362c8e1b69
11 changed files with 685 additions and 43 deletions
|
|
@ -2,50 +2,159 @@
|
|||
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qobject.h>
|
||||
#include <qproperty.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "toplevel_mapping.hpp"
|
||||
#include "../../toplevel_management/handle.hpp"
|
||||
#include "../../toplevel_management/qml.hpp"
|
||||
#include "connection.hpp"
|
||||
#include "toplevel_mapping.hpp"
|
||||
#include "workspace.hpp"
|
||||
|
||||
using namespace qs::wayland::toplevel_management;
|
||||
using namespace qs::wayland::toplevel_management::impl;
|
||||
|
||||
namespace qs::hyprland::ipc {
|
||||
|
||||
HyprlandToplevel::HyprlandToplevel(Toplevel* toplevel)
|
||||
: QObject(toplevel)
|
||||
, handle(toplevel->implHandle()) {
|
||||
auto* instance = HyprlandToplevelMappingManager::instance();
|
||||
auto addr = instance->getToplevelAddress(handle);
|
||||
HyprlandToplevel::HyprlandToplevel(HyprlandIpc* ipc): QObject(ipc), ipc(ipc) {
|
||||
this->bMonitor.setBinding([this]() {
|
||||
return this->bWorkspace ? this->bWorkspace->bindableMonitor().value() : nullptr;
|
||||
});
|
||||
|
||||
if (addr != 0) this->setAddress(addr);
|
||||
else {
|
||||
QObject::connect(
|
||||
instance,
|
||||
&HyprlandToplevelMappingManager::toplevelAddressed,
|
||||
this,
|
||||
&HyprlandToplevel::onToplevelAddressed
|
||||
);
|
||||
}
|
||||
this->bActivated.setBinding([this]() {
|
||||
return this->ipc->bindableActiveToplevel().value() == this;
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
this,
|
||||
&HyprlandToplevel::activatedChanged,
|
||||
this,
|
||||
&HyprlandToplevel::onActivatedChanged
|
||||
);
|
||||
}
|
||||
|
||||
void HyprlandToplevel::onToplevelAddressed(ToplevelHandle* handle, quint64 address) {
|
||||
if (handle == this->handle) {
|
||||
this->setAddress(address);
|
||||
QObject::disconnect(HyprlandToplevelMappingManager::instance(), nullptr, this, nullptr);
|
||||
HyprlandToplevel::HyprlandToplevel(HyprlandIpc* ipc, Toplevel* toplevel): HyprlandToplevel(ipc) {
|
||||
this->mWaylandHandle = toplevel->implHandle();
|
||||
auto* instance = HyprlandToplevelMappingManager::instance();
|
||||
auto addr = instance->getToplevelAddress(this->mWaylandHandle);
|
||||
|
||||
if (!addr) {
|
||||
// Address not available, will rely on HyprlandIpc to resolve it.
|
||||
return;
|
||||
}
|
||||
|
||||
this->setAddress(addr);
|
||||
|
||||
// Check if client is present in HyprlandIPC
|
||||
auto* hyprToplevel = ipc->findToplevelByAddress(addr, false);
|
||||
// HyprlandIpc will eventually resolve it
|
||||
if (!hyprToplevel) return;
|
||||
|
||||
this->setHyprlandHandle(hyprToplevel);
|
||||
}
|
||||
|
||||
void HyprlandToplevel::updateInitial(
|
||||
quint64 address,
|
||||
const QString& title,
|
||||
const QString& workspaceName
|
||||
) {
|
||||
auto* workspace = this->ipc->findWorkspaceByName(workspaceName, false);
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
this->setAddress(address);
|
||||
this->bTitle = title;
|
||||
this->setWorkspace(workspace);
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
void HyprlandToplevel::updateFromObject(const QVariantMap& object) {
|
||||
auto addressStr = object.value("address").value<QString>();
|
||||
auto title = object.value("title").value<QString>();
|
||||
|
||||
bool ok = false;
|
||||
auto address = addressStr.toULongLong(&ok, 16);
|
||||
if (!ok || !address) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->setAddress(address);
|
||||
this->bTitle = title;
|
||||
|
||||
auto workspaceMap = object.value("workspace").toMap();
|
||||
auto workspaceName = workspaceMap.value("name").toString();
|
||||
|
||||
auto* workspace = this->ipc->findWorkspaceByName(workspaceName, false);
|
||||
if (!workspace) return;
|
||||
|
||||
this->setWorkspace(workspace);
|
||||
}
|
||||
|
||||
void HyprlandToplevel::setWorkspace(HyprlandWorkspace* workspace) {
|
||||
auto* oldWorkspace = this->bWorkspace.value();
|
||||
if (oldWorkspace == workspace) return;
|
||||
|
||||
if (oldWorkspace) {
|
||||
QObject::disconnect(oldWorkspace, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->bWorkspace = workspace;
|
||||
|
||||
if (workspace) {
|
||||
QObject::connect(workspace, &QObject::destroyed, this, [this]() {
|
||||
this->bWorkspace = nullptr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void HyprlandToplevel::setAddress(quint64 address) {
|
||||
this->mAddress = QString::number(address, 16);
|
||||
this->mAddress = address;
|
||||
emit this->addressChanged();
|
||||
}
|
||||
|
||||
Toplevel* HyprlandToplevel::waylandHandle() {
|
||||
return ToplevelManager::instance()->forImpl(this->mWaylandHandle);
|
||||
}
|
||||
|
||||
void HyprlandToplevel::setWaylandHandle(impl::ToplevelHandle* handle) {
|
||||
if (this->mWaylandHandle == handle) return;
|
||||
if (this->mWaylandHandle) {
|
||||
QObject::disconnect(this->mWaylandHandle, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mWaylandHandle = handle;
|
||||
if (handle) {
|
||||
QObject::connect(handle, &QObject::destroyed, this, [this]() {
|
||||
this->mWaylandHandle = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
emit this->waylandHandleChanged();
|
||||
}
|
||||
|
||||
void HyprlandToplevel::setHyprlandHandle(HyprlandToplevel* handle) {
|
||||
if (this->mHyprlandHandle == handle) return;
|
||||
if (this->mHyprlandHandle) {
|
||||
QObject::disconnect(this->mHyprlandHandle, nullptr, this, nullptr);
|
||||
}
|
||||
this->mHyprlandHandle = handle;
|
||||
if (handle) {
|
||||
QObject::connect(handle, &QObject::destroyed, this, [this]() {
|
||||
this->mHyprlandHandle = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
emit this->hyprlandHandleChanged();
|
||||
}
|
||||
|
||||
void HyprlandToplevel::onActivatedChanged() {
|
||||
if (this->bUrgent.value()) {
|
||||
// If was urgent, and now active, clear urgent state
|
||||
this->bUrgent = false;
|
||||
}
|
||||
}
|
||||
|
||||
HyprlandToplevel* HyprlandToplevel::qmlAttachedProperties(QObject* object) {
|
||||
if (auto* toplevel = qobject_cast<Toplevel*>(object)) {
|
||||
return new HyprlandToplevel(toplevel);
|
||||
auto* ipc = HyprlandIpc::instance();
|
||||
return new HyprlandToplevel(ipc, toplevel);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue