From 96bf5f33653218cbce7e69334e621914c84d4221 Mon Sep 17 00:00:00 2001 From: zach Date: Wed, 20 May 2026 06:50:14 +0200 Subject: [PATCH] cleanup for hyprland lua configs --- Config/DynamicColors.qml | 13 +- Drawers/Windows.qml | 2 +- Modules/Workspaces.qml | 3 +- Plugins/ZShell/Internal/hyprextras.cpp | 288 +++++++++++++------------ Plugins/ZShell/Internal/hyprextras.hpp | 64 +++--- 5 files changed, 194 insertions(+), 176 deletions(-) diff --git a/Config/DynamicColors.qml b/Config/DynamicColors.qml index 84d16df..876c7d7 100644 --- a/Config/DynamicColors.qml +++ b/Config/DynamicColors.qml @@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound import Quickshell import Quickshell.Io +import Quickshell.Hyprland import QtQuick import ZShell import qs.Helpers @@ -79,8 +80,8 @@ Singleton { } function reloadHyprRules(): void { - const barStr = "keyword layerrule %1 %2, match:namespace ZShell-Bar"; - const authStr = "keyword layerrule %1 %2, match:namespace ZShell-Auth"; + const barStr = Hyprland.usingLua ? `eval 'hl.layer_rule({ match = { namespace = "ZShell-Bar" }, %1 = true, %2 = true })'` : "keyword layerrule %1 %2, match:namespace ZShell-Bar"; + const authStr = Hyprland.usingLua ? `eval 'hl.layer_rule({ match = { namespace = "ZShell-Auth" }, %1 = true, %2 = true })'` : "keyword layerrule %1 %2, match:namespace ZShell-Auth"; Hypr.extras.batchMessage([barStr.arg("blur").arg(transparency.enabled ? 1 : 0), barStr.arg("ignore_alpha").arg(transparency.base - 0.03)]); Hypr.extras.batchMessage([authStr.arg("blur").arg(transparency.enabled ? 1 : 0), authStr.arg("ignore_alpha").arg(transparency.base - 0.03)]); } @@ -93,6 +94,14 @@ Singleton { Component.onCompleted: debounceTimer.triggered() + Connections { + function onUsingLuaChanged(): void { + root.reloadHyprRules(); + } + + target: Hyprland + } + Connections { function onConfigReloaded(): void { root.reloadHyprRules(); diff --git a/Drawers/Windows.qml b/Drawers/Windows.qml index 8e892ee..9f9e4ca 100644 --- a/Drawers/Windows.qml +++ b/Drawers/Windows.qml @@ -279,7 +279,7 @@ Variants { deformAmount: 0.08 implicitHeight: panels.settings.height * (1 + extraHeight) implicitWidth: panels.settings.width - panel: panels.settings + panel: panels.settingsWrapper radius: Appearance.rounding.large topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller topRightRadius: Appearance.rounding.large + Appearance.padding.smaller diff --git a/Modules/Workspaces.qml b/Modules/Workspaces.qml index c8f52c6..30ee987 100644 --- a/Modules/Workspaces.qml +++ b/Modules/Workspaces.qml @@ -79,7 +79,8 @@ Item { } onPressed: { - Hyprland.dispatch(`workspace ${button.modelData.name}`); + const ws = button.modelData.name; + Hyprland.dispatch(Hyprland.usingLua ? `hl.dsp.focus({ workspace= "${ws}"})` : `workspace ${ws}`); } } } diff --git a/Plugins/ZShell/Internal/hyprextras.cpp b/Plugins/ZShell/Internal/hyprextras.cpp index 6ff5f3b..a869ae2 100644 --- a/Plugins/ZShell/Internal/hyprextras.cpp +++ b/Plugins/ZShell/Internal/hyprextras.cpp @@ -1,217 +1,221 @@ #include "hyprextras.hpp" +#include "hyprdevices.hpp" #include #include #include +#include #include +Q_LOGGING_CATEGORY(lcHypr, "ZShell.internal.hypr", QtInfoMsg) + namespace ZShell::internal::hypr { HyprExtras::HyprExtras(QObject* parent) - : QObject(parent) - , m_requestSocket("") - , m_eventSocket("") - , m_socket(nullptr) - , m_socketValid(false) - , m_devices(new HyprDevices(this)) { - const auto his = qEnvironmentVariable("HYPRLAND_INSTANCE_SIGNATURE"); - if (his.isEmpty()) { - qWarning() - << "HyprExtras::HyprExtras: $HYPRLAND_INSTANCE_SIGNATURE is unset. Unable to connect to Hyprland socket."; - return; - } + : QObject(parent) + , m_requestSocket("") + , m_eventSocket("") + , m_socket(nullptr) + , m_socketValid(false) + , m_devices(new HyprDevices(this)) { + const auto his = qEnvironmentVariable("HYPRLAND_INSTANCE_SIGNATURE"); + if (his.isEmpty()) { + qCWarning(lcHypr) << "$HYPRLAND_INSTANCE_SIGNATURE is unset. Unable to connect to Hyprland socket."; + return; + } - auto hyprDir = QString("%1/hypr/%2").arg(qEnvironmentVariable("XDG_RUNTIME_DIR"), his); - if (!QDir(hyprDir).exists()) { - hyprDir = "/tmp/hypr/" + his; + auto hyprDir = QString("%1/hypr/%2").arg(qEnvironmentVariable("XDG_RUNTIME_DIR"), his); + if (!QDir(hyprDir).exists()) { + hyprDir = "/tmp/hypr/" + his; - if (!QDir(hyprDir).exists()) { - qWarning() << "HyprExtras::HyprExtras: Hyprland socket directory does not exist. Unable to connect to " - "Hyprland socket."; - return; - } - } + if (!QDir(hyprDir).exists()) { + qCWarning(lcHypr) << "Hyprland socket directory does not exist. Unable to connect to Hyprland socket."; + return; + } + } - m_requestSocket = hyprDir + "/.socket.sock"; - m_eventSocket = hyprDir + "/.socket2.sock"; + m_requestSocket = hyprDir + "/.socket.sock"; + m_eventSocket = hyprDir + "/.socket2.sock"; - refreshOptions(); - refreshDevices(); + refreshOptions(); + refreshDevices(); - m_socket = new QLocalSocket(this); + m_socket = new QLocalSocket(this); - QObject::connect(m_socket, &QLocalSocket::errorOccurred, this, &HyprExtras::socketError); - QObject::connect(m_socket, &QLocalSocket::stateChanged, this, &HyprExtras::socketStateChanged); - QObject::connect(m_socket, &QLocalSocket::readyRead, this, &HyprExtras::readEvent); + QObject::connect(m_socket, &QLocalSocket::errorOccurred, this, &HyprExtras::socketError); + QObject::connect(m_socket, &QLocalSocket::stateChanged, this, &HyprExtras::socketStateChanged); + QObject::connect(m_socket, &QLocalSocket::readyRead, this, &HyprExtras::readEvent); - m_socket->connectToServer(m_eventSocket, QLocalSocket::ReadOnly); + m_socket->connectToServer(m_eventSocket, QLocalSocket::ReadOnly); } QVariantHash HyprExtras::options() const { - return m_options; + return m_options; } HyprDevices* HyprExtras::devices() const { - return m_devices; + return m_devices; } void HyprExtras::message(const QString& message) { - if (message.isEmpty()) { - return; - } + if (message.isEmpty()) { + return; + } - makeRequest(message, [](bool success, const QByteArray& res) { - if (!success) { - qWarning() << "HyprExtras::message: request error:" << QString::fromUtf8(res); - } - }); + makeRequest(message, [](bool success, const QByteArray& res) { + if (!success) { + qCWarning(lcHypr) << "message: request error:" << QString::fromUtf8(res); + } + }); } void HyprExtras::batchMessage(const QStringList& messages) { - if (messages.isEmpty()) { - return; - } + if (messages.isEmpty()) { + return; + } - makeRequest("[[BATCH]]" + messages.join(";"), [](bool success, const QByteArray& res) { - if (!success) { - qWarning() << "HyprExtras::batchMessage: request error:" << QString::fromUtf8(res); - } - }); + makeRequest("[[BATCH]]" + messages.join(";"), [](bool success, const QByteArray& res) { + if (!success) { + qCWarning(lcHypr) << "batchMessage: request error:" << QString::fromUtf8(res); + } + }); } void HyprExtras::applyOptions(const QVariantHash& options) { - if (options.isEmpty()) { - return; - } + if (options.isEmpty()) { + return; + } - QString request = "[[BATCH]]"; - for (auto it = options.constBegin(); it != options.constEnd(); ++it) { - request += QString("keyword %1 %2;").arg(it.key(), it.value().toString()); - } + QString request; + request.reserve(12 + options.size() * 40); + request += QLatin1String("[[BATCH]]"); + for (auto it = options.constBegin(); it != options.constEnd(); ++it) { + request += QLatin1String("keyword ") + it.key() + QLatin1Char(' ') + it.value().toString() + QLatin1Char(';'); + } - makeRequest(request, [this](bool success, const QByteArray& res) { - if (success) { - refreshOptions(); - } else { - qWarning() << "HyprExtras::applyOptions: request error" << QString::fromUtf8(res); - } - }); + makeRequest(request, [this](bool success, const QByteArray& res) { + if (success) { + refreshOptions(); + } else { + qCWarning(lcHypr) << "applyOptions: request error" << QString::fromUtf8(res); + } + }); } void HyprExtras::refreshOptions() { - if (!m_optionsRefresh.isNull()) { - m_optionsRefresh->close(); - } + if (!m_optionsRefresh.isNull()) { + m_optionsRefresh->close(); + } - m_optionsRefresh = makeRequestJson("descriptions", [this](bool success, const QJsonDocument& response) { - m_optionsRefresh.reset(); - if (!success) { - return; - } + m_optionsRefresh = makeRequestJson("descriptions", [this](bool success, const QJsonDocument& response) { + m_optionsRefresh.reset(); + if (!success) { + return; + } - const auto options = response.array(); - bool dirty = false; + const auto options = response.array(); + bool dirty = false; - for (const auto& o : std::as_const(options)) { - const auto obj = o.toObject(); - const auto key = obj.value("value").toString(); - const auto value = obj.value("data").toObject().value("current").toVariant(); - if (m_options.value(key) != value) { - dirty = true; - m_options.insert(key, value); - } - } + for (const auto& o : std::as_const(options)) { + const auto obj = o.toObject(); + const auto key = obj.value("value").toString(); + const auto value = obj.value("data").toObject().value("current").toVariant(); + if (m_options.value(key) != value) { + dirty = true; + m_options.insert(key, value); + } + } - if (dirty) { - emit optionsChanged(); - } - }); + if (dirty) { + emit optionsChanged(); + } + }); } void HyprExtras::refreshDevices() { - if (!m_devicesRefresh.isNull()) { - m_devicesRefresh->close(); - } + if (!m_devicesRefresh.isNull()) { + m_devicesRefresh->close(); + } - m_devicesRefresh = makeRequestJson("devices", [this](bool success, const QJsonDocument& response) { - m_devicesRefresh.reset(); - if (success) { - m_devices->updateLastIpcObject(response.object()); - } - }); + m_devicesRefresh = makeRequestJson("devices", [this](bool success, const QJsonDocument& response) { + m_devicesRefresh.reset(); + if (success) { + m_devices->updateLastIpcObject(response.object()); + } + }); } void HyprExtras::socketError(QLocalSocket::LocalSocketError error) const { - if (!m_socketValid) { - qWarning() << "HyprExtras::socketError: unable to connect to Hyprland event socket:" << error; - } else { - qWarning() << "HyprExtras::socketError: Hyprland event socket error:" << error; - } + if (!m_socketValid) { + qCWarning(lcHypr) << "socketError: unable to connect to Hyprland event socket:" << error; + } else { + qCWarning(lcHypr) << "socketError: Hyprland event socket error:" << error; + } } void HyprExtras::socketStateChanged(QLocalSocket::LocalSocketState state) { - if (state == QLocalSocket::UnconnectedState && m_socketValid) { - qWarning() << "HyprExtras::socketStateChanged: Hyprland event socket disconnected."; - } + if (state == QLocalSocket::UnconnectedState && m_socketValid) { + qCWarning(lcHypr) << "socketStateChanged: Hyprland event socket disconnected."; + } - m_socketValid = state == QLocalSocket::ConnectedState; + m_socketValid = state == QLocalSocket::ConnectedState; } void HyprExtras::readEvent() { - while (true) { - auto rawEvent = m_socket->readLine(); - if (rawEvent.isEmpty()) { - break; - } - rawEvent.truncate(rawEvent.length() - 1); // Remove trailing \n - const auto event = QByteArrayView(rawEvent.data(), rawEvent.indexOf(">>")); - handleEvent(QString::fromUtf8(event)); - } + while (true) { + auto rawEvent = m_socket->readLine(); + if (rawEvent.isEmpty()) { + break; + } + rawEvent.truncate(rawEvent.length() - 1); // Remove trailing \n + const auto event = QByteArrayView(rawEvent.data(), rawEvent.indexOf(">>")); + handleEvent(QString::fromUtf8(event)); + } } void HyprExtras::handleEvent(const QString& event) { - if (event == "configreloaded") { - refreshOptions(); - } else if (event == "activelayout") { - refreshDevices(); - } + if (event == "configreloaded") { + refreshOptions(); + } else if (event == "activelayout") { + refreshDevices(); + } } HyprExtras::SocketPtr HyprExtras::makeRequestJson( - const QString& request, const std::function& callback) { - return makeRequest("j/" + request, [callback](bool success, const QByteArray& response) { - callback(success, QJsonDocument::fromJson(response)); - }); + const QString& request, const std::function& callback) { + return makeRequest("j/" + request, [callback](bool success, const QByteArray& response) { + callback(success, QJsonDocument::fromJson(response)); + }); } HyprExtras::SocketPtr HyprExtras::makeRequest( - const QString& request, const std::function& callback) { - if (m_requestSocket.isEmpty()) { - return SocketPtr(); - } + const QString& request, const std::function& callback) { + if (m_requestSocket.isEmpty()) { + return SocketPtr(); + } - auto socket = SocketPtr::create(this); + auto socket = SocketPtr::create(this); - QObject::connect(socket.data(), &QLocalSocket::connected, this, [=, this]() { - QObject::connect(socket.data(), &QLocalSocket::readyRead, this, [socket, callback]() { - const auto response = socket->readAll(); - callback(true, std::move(response)); - socket->close(); - }); + QObject::connect(socket.data(), &QLocalSocket::connected, this, [=, this]() { + QObject::connect(socket.data(), &QLocalSocket::readyRead, this, [socket, callback]() { + const auto response = socket->readAll(); + callback(true, std::move(response)); + socket->close(); + }); - socket->write(request.toUtf8()); - socket->flush(); - }); + socket->write(request.toUtf8()); + socket->flush(); + }); - QObject::connect(socket.data(), &QLocalSocket::errorOccurred, this, [=](QLocalSocket::LocalSocketError err) { - qWarning() << "HyprExtras::makeRequest: error making request:" << err << "| request:" << request; - callback(false, {}); - socket->close(); - }); + QObject::connect(socket.data(), &QLocalSocket::errorOccurred, this, [=](QLocalSocket::LocalSocketError err) { + qCWarning(lcHypr) << "makeRequest: error making request:" << err << "| request:" << request; + callback(false, {}); + socket->close(); + }); - socket->connectToServer(m_requestSocket); + socket->connectToServer(m_requestSocket); - return socket; + return socket; } } // namespace ZShell::internal::hypr diff --git a/Plugins/ZShell/Internal/hyprextras.hpp b/Plugins/ZShell/Internal/hyprextras.hpp index ee58170..fb4ba00 100644 --- a/Plugins/ZShell/Internal/hyprextras.hpp +++ b/Plugins/ZShell/Internal/hyprextras.hpp @@ -1,56 +1,60 @@ #pragma once -#include "hyprdevices.hpp" #include #include #include +#include +#include namespace ZShell::internal::hypr { -class HyprExtras : public QObject { - Q_OBJECT - QML_ELEMENT +class HyprDevices; - Q_PROPERTY(QVariantHash options READ options NOTIFY optionsChanged) - Q_PROPERTY(ZShell::internal::hypr::HyprDevices* devices READ devices CONSTANT) +class HyprExtras : public QObject { +Q_OBJECT +QML_ELEMENT + Q_MOC_INCLUDE("hyprdevices.hpp") + +Q_PROPERTY(QVariantHash options READ options NOTIFY optionsChanged) +Q_PROPERTY(ZShell::internal::hypr::HyprDevices* devices READ devices CONSTANT) public: - explicit HyprExtras(QObject* parent = nullptr); +explicit HyprExtras(QObject* parent = nullptr); - [[nodiscard]] QVariantHash options() const; - [[nodiscard]] HyprDevices* devices() const; +[[nodiscard]] QVariantHash options() const; +[[nodiscard]] HyprDevices* devices() const; - Q_INVOKABLE void message(const QString& message); - Q_INVOKABLE void batchMessage(const QStringList& messages); - Q_INVOKABLE void applyOptions(const QVariantHash& options); +Q_INVOKABLE void message(const QString& message); +Q_INVOKABLE void batchMessage(const QStringList& messages); +Q_INVOKABLE void applyOptions(const QVariantHash& options); - Q_INVOKABLE void refreshOptions(); - Q_INVOKABLE void refreshDevices(); +Q_INVOKABLE void refreshOptions(); +Q_INVOKABLE void refreshDevices(); signals: - void optionsChanged(); +void optionsChanged(); private: - using SocketPtr = QSharedPointer; +using SocketPtr = QSharedPointer; - QString m_requestSocket; - QString m_eventSocket; - QLocalSocket* m_socket; - bool m_socketValid; +QString m_requestSocket; +QString m_eventSocket; +QLocalSocket* m_socket; +bool m_socketValid; - QVariantHash m_options; - HyprDevices* const m_devices; +QVariantHash m_options; +HyprDevices* const m_devices; - SocketPtr m_optionsRefresh; - SocketPtr m_devicesRefresh; +SocketPtr m_optionsRefresh; +SocketPtr m_devicesRefresh; - void socketError(QLocalSocket::LocalSocketError error) const; - void socketStateChanged(QLocalSocket::LocalSocketState state); - void readEvent(); - void handleEvent(const QString& event); +void socketError(QLocalSocket::LocalSocketError error) const; +void socketStateChanged(QLocalSocket::LocalSocketState state); +void readEvent(); +void handleEvent(const QString& event); - SocketPtr makeRequestJson(const QString& request, const std::function& callback); - SocketPtr makeRequest(const QString& request, const std::function& callback); +SocketPtr makeRequestJson(const QString& request, const std::function& callback); +SocketPtr makeRequest(const QString& request, const std::function& callback); }; } // namespace ZShell::internal::hypr