diff --git a/changelog/next.md b/changelog/next.md index bbd6356..638eeb8 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -31,6 +31,7 @@ set shell id. - Added per-corner radius support to Region. - Added ColorQuantizer region selection. - Added dialog window support to FloatingWindow. +- Added lua config support to Hyprland module. ## Other Changes diff --git a/src/wayland/hyprland/ipc/connection.cpp b/src/wayland/hyprland/ipc/connection.cpp index d15701d..a258d21 100644 --- a/src/wayland/hyprland/ipc/connection.cpp +++ b/src/wayland/hyprland/ipc/connection.cpp @@ -74,10 +74,23 @@ HyprlandIpc::HyprlandIpc() { // clang-format on - this->eventSocket.connectToServer(this->mEventSocketPath, QLocalSocket::ReadOnly); - this->refreshMonitors(true); - this->refreshWorkspaces(true); - this->refreshToplevels(); + this->makeRequest("j/status", [&](bool success, QByteArray resp) { + if (success) { + this->bUsingLua = [&]() { + if (resp == "unknown request") return false; + auto json = QJsonDocument::fromJson(resp).object(); + auto provider = json.value("configProvider"); + return provider == "lua"; + }(); + } else { + qCWarning(logHyprlandIpc) << "Hyprland ipc status request failed."; + } + + this->eventSocket.connectToServer(this->mEventSocketPath, QLocalSocket::ReadOnly); + this->refreshMonitors(true); + this->refreshWorkspaces(true); + this->refreshToplevels(); + }); } QString HyprlandIpc::requestSocketPath() const { return this->mRequestSocketPath; } diff --git a/src/wayland/hyprland/ipc/connection.hpp b/src/wayland/hyprland/ipc/connection.hpp index ba1e7c9..c617c04 100644 --- a/src/wayland/hyprland/ipc/connection.hpp +++ b/src/wayland/hyprland/ipc/connection.hpp @@ -81,6 +81,8 @@ public: [[nodiscard]] HyprlandMonitor* monitorFor(QuickshellScreenInfo* screen); + [[nodiscard]] QBindable bindableUsingLua() const { return &this->bUsingLua; } + [[nodiscard]] QBindable bindableFocusedMonitor() const { return &this->bFocusedMonitor; } @@ -116,6 +118,7 @@ signals: void connected(); void rawEvent(HyprlandIpcEvent* event); + void usingLuaChanged(); void focusedMonitorChanged(); void focusedWorkspaceChanged(); void activeToplevelChanged(); @@ -155,6 +158,8 @@ private: HyprlandIpcEvent event {this}; + Q_OBJECT_BINDABLE_PROPERTY(HyprlandIpc, bool, bUsingLua, &HyprlandIpc::usingLuaChanged); + Q_OBJECT_BINDABLE_PROPERTY( HyprlandIpc, HyprlandMonitor*, diff --git a/src/wayland/hyprland/ipc/qml.cpp b/src/wayland/hyprland/ipc/qml.cpp index eb5fdc6..3b1ce52 100644 --- a/src/wayland/hyprland/ipc/qml.cpp +++ b/src/wayland/hyprland/ipc/qml.cpp @@ -51,6 +51,10 @@ void HyprlandIpcQml::refreshToplevels() { HyprlandIpc::instance()->refreshToplev QString HyprlandIpcQml::requestSocketPath() { return HyprlandIpc::instance()->requestSocketPath(); } QString HyprlandIpcQml::eventSocketPath() { return HyprlandIpc::instance()->eventSocketPath(); } +QBindable HyprlandIpcQml::bindableUsingLua() { + return HyprlandIpc::instance()->bindableUsingLua(); +} + QBindable HyprlandIpcQml::bindableFocusedMonitor() { return HyprlandIpc::instance()->bindableFocusedMonitor(); } diff --git a/src/wayland/hyprland/ipc/qml.hpp b/src/wayland/hyprland/ipc/qml.hpp index ebf5d80..b9a8d5e 100644 --- a/src/wayland/hyprland/ipc/qml.hpp +++ b/src/wayland/hyprland/ipc/qml.hpp @@ -16,6 +16,10 @@ namespace qs::hyprland::ipc { class HyprlandIpcQml: public QObject { Q_OBJECT; // clang-format off + /// True if Hyprland is running in lua mode. Dispatcher syntax changes when using lua. + /// + /// This property will be false until the Hyprland module is initialized. + Q_PROPERTY(bool usingLua READ default NOTIFY usingLuaChanged BINDABLE bindableUsingLua); /// Path to the request socket (.socket.sock) Q_PROPERTY(QString requestSocketPath READ requestSocketPath CONSTANT); /// Path to the event socket (.socket2.sock) @@ -70,6 +74,7 @@ public: [[nodiscard]] static QString requestSocketPath(); [[nodiscard]] static QString eventSocketPath(); + [[nodiscard]] static QBindable bindableUsingLua(); [[nodiscard]] static QBindable bindableFocusedMonitor(); [[nodiscard]] static QBindable bindableFocusedWorkspace(); [[nodiscard]] static QBindable bindableActiveToplevel(); @@ -83,6 +88,7 @@ signals: /// See [Hyprland Wiki: IPC](https://wiki.hyprland.org/IPC/) for a list of events. void rawEvent(qs::hyprland::ipc::HyprlandIpcEvent* event); + void usingLuaChanged(); void focusedMonitorChanged(); void focusedWorkspaceChanged(); void activeToplevelChanged(); diff --git a/src/wayland/hyprland/ipc/workspace.cpp b/src/wayland/hyprland/ipc/workspace.cpp index c5d63b0..44377c0 100644 --- a/src/wayland/hyprland/ipc/workspace.cpp +++ b/src/wayland/hyprland/ipc/workspace.cpp @@ -151,7 +151,20 @@ void HyprlandWorkspace::clearUrgent() { } void HyprlandWorkspace::activate() { - this->ipc->dispatch(QString("workspace %1").arg(this->bName.value())); + if (this->ipc->bindableUsingLua().value()) { + QString name; + for (const auto c: this->bName.value()) { + switch (c.toLatin1()) { + case '"': name.append("\\\""); break; + case '\\': name.append("\\\\"); break; + default: name.append(c); break; + } + } + + this->ipc->dispatch(QString("hl.dsp.focus({ workspace = \"%1\" })").arg(name)); + } else { + this->ipc->dispatch(QString("workspace %1").arg(this->bName.value())); + } } } // namespace qs::hyprland::ipc