#include "qml.hpp" #include #include #include #include #include #include #include #include "../../../core/proxywindow.hpp" #include "../../../core/windowinterface.hpp" #include "grab.hpp" #include "manager.hpp" namespace qs::hyprland { using focus_grab::FocusGrab; using focus_grab::FocusGrabManager; void HyprlandFocusGrab::componentComplete() { this->tryActivate(); } bool HyprlandFocusGrab::isActive() const { return this->grab != nullptr && this->grab->isActive(); } void HyprlandFocusGrab::setActive(bool active) { if (active == this->targetActive) return; this->targetActive = active; if (!active) { delete this->grab; this->grab = nullptr; emit this->activeChanged(); } else { this->tryActivate(); } } QObjectList HyprlandFocusGrab::windows() const { return this->windowObjects; } void HyprlandFocusGrab::setWindows(QObjectList windows) { if (windows == this->windowObjects) return; this->windowObjects = std::move(windows); this->syncWindows(); emit this->windowsChanged(); } void HyprlandFocusGrab::onGrabActivated() { emit this->activeChanged(); } void HyprlandFocusGrab::onGrabCleared() { emit this->cleared(); this->setActive(false); } void HyprlandFocusGrab::onProxyConnected() { if (this->grab != nullptr) { this->grab->addWindow(qobject_cast(this->sender())->backingWindow()); this->grab->sync(); } } void HyprlandFocusGrab::tryActivate() { if (!this->targetActive || this->isActive()) return; auto* manager = FocusGrabManager::instance(); if (!manager->isActive()) { qWarning() << "The active compositor does not support the hyprland_focus_grab_v1 protocol. " "HyprlandFocusGrab will not work."; qWarning() << "** Learn why $XDG_CURRENT_DESKTOP sucks and download a better compositor " "today at https://hyprland.org"; return; } this->grab = manager->createGrab(); this->grab->setParent(this); QObject::connect(this->grab, &FocusGrab::activated, this, &HyprlandFocusGrab::onGrabActivated); QObject::connect(this->grab, &FocusGrab::cleared, this, &HyprlandFocusGrab::onGrabCleared); for (auto* proxy: this->trackedProxies) { if (proxy->backingWindow() != nullptr) { this->grab->addWindow(proxy->backingWindow()); } } this->grab->sync(); } void HyprlandFocusGrab::syncWindows() { auto newProxy = QList(); for (auto* windowObject: this->windowObjects) { auto* proxyWindow = qobject_cast(windowObject); if (proxyWindow == nullptr) { if (auto* iface = qobject_cast(windowObject)) { proxyWindow = iface->proxyWindow(); } } if (proxyWindow != nullptr) { newProxy.push_back(proxyWindow); } } for (auto* oldWindow: this->trackedProxies) { if (!newProxy.contains(oldWindow)) { QObject::disconnect(oldWindow, nullptr, this, nullptr); if (this->grab != nullptr && oldWindow->backingWindow() != nullptr) { this->grab->removeWindow(oldWindow->backingWindow()); } } } for (auto* newProxy: newProxy) { if (!this->trackedProxies.contains(newProxy)) { QObject::connect( newProxy, &ProxyWindowBase::windowConnected, this, &HyprlandFocusGrab::onProxyConnected ); if (this->grab != nullptr && newProxy->backingWindow() != nullptr) { this->grab->addWindow(newProxy->backingWindow()); } } } this->trackedProxies = newProxy; if (this->grab != nullptr) this->grab->sync(); } } // namespace qs::hyprland