diff --git a/hyprctl/hw-protocols/hyprpaper_core.xml b/hyprctl/hw-protocols/hyprpaper_core.xml index fa2edc0a..3d26a102 100644 --- a/hyprctl/hw-protocols/hyprpaper_core.xml +++ b/hyprctl/hw-protocols/hyprpaper_core.xml @@ -1,5 +1,5 @@ - + BSD 3-Clause License @@ -31,7 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - + This is the core manager object for hyprpaper operations @@ -62,6 +62,13 @@ Destroys this object. Children remain alive until destroyed. + + + + Creates a status object + + + @@ -141,4 +148,25 @@ + + + + This is an object which will emit various status updates. + + + + + Sends the active wallpaper for a given monitor. This will be emitted + immediately after binding, and then every time the path changes. + + + + + + + + Destroys this object. + + + diff --git a/hyprctl/src/hyprpaper/Hyprpaper.cpp b/hyprctl/src/hyprpaper/Hyprpaper.cpp index 7c74d7ce..93f4182a 100644 --- a/hyprctl/src/hyprpaper/Hyprpaper.cpp +++ b/hyprctl/src/hyprpaper/Hyprpaper.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -15,7 +16,7 @@ using namespace std::string_literals; constexpr const char* SOCKET_NAME = ".hyprpaper.sock"; static SP g_coreImpl; -constexpr const uint32_t PROTOCOL_VERSION_SUPPORTED = 1; +constexpr const uint32_t PROTOCOL_VERSION_SUPPORTED = 2; // static hyprpaperCoreWallpaperFitMode fitFromString(const std::string_view& sv) { @@ -53,21 +54,7 @@ static std::expected getFullPath(const std::string_vie return resolvePath(sv); } -std::expected Hyprpaper::makeHyprpaperRequest(const std::string_view& rq) { - if (!rq.contains(' ')) - return std::unexpected("Invalid request"); - - if (!rq.starts_with("/hyprpaper ")) - return std::unexpected("Invalid request"); - - std::string_view LHS, RHS; - auto spacePos = rq.find(' ', 12); - LHS = rq.substr(11, spacePos - 11); - RHS = rq.substr(spacePos + 1); - - if (LHS != "wallpaper") - return std::unexpected("Unknown hyprpaper request"); - +static std::expected doWallpaper(const std::string_view& RHS) { CVarList2 args(std::string{RHS}, 0, ','); const std::string MONITOR = std::string{args[0]}; @@ -99,7 +86,7 @@ std::expected Hyprpaper::makeHyprpaperRequest(const std::stri if (!socket) return std::unexpected("can't send: failed to connect to hyprpaper (is it running?)"); - g_coreImpl = makeShared(1); + g_coreImpl = makeShared(PROTOCOL_VERSION_SUPPORTED); socket->addImplementation(g_coreImpl); @@ -111,7 +98,7 @@ std::expected Hyprpaper::makeHyprpaperRequest(const std::stri if (!spec) return std::unexpected("can't send: hyprpaper doesn't have the spec?!"); - auto manager = makeShared(socket->bindProtocol(g_coreImpl->protocol(), PROTOCOL_VERSION_SUPPORTED)); + auto manager = makeShared(socket->bindProtocol(g_coreImpl->protocol(), std::min(PROTOCOL_VERSION_SUPPORTED, spec->specVer()))); if (!manager) return std::unexpected("wire error: couldn't create manager"); @@ -150,3 +137,72 @@ std::expected Hyprpaper::makeHyprpaperRequest(const std::stri return {}; } + +static std::expected doListActive() { + const auto RTDIR = getenv("XDG_RUNTIME_DIR"); + + if (!RTDIR || RTDIR[0] == '\0') + return std::unexpected("can't send: no XDG_RUNTIME_DIR"); + + const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE"); + + if (!HIS || HIS[0] == '\0') + return std::unexpected("can't send: no HYPRLAND_INSTANCE_SIGNATURE (not running under hyprland)"); + + auto socketPath = RTDIR + "/hypr/"s + HIS + "/"s + SOCKET_NAME; + + auto socket = Hyprwire::IClientSocket::open(socketPath); + + if (!socket) + return std::unexpected("can't send: failed to connect to hyprpaper (is it running?)"); + + g_coreImpl = makeShared(PROTOCOL_VERSION_SUPPORTED); + + socket->addImplementation(g_coreImpl); + + if (!socket->waitForHandshake()) + return std::unexpected("can't send: wire handshake failed"); + + auto spec = socket->getSpec(g_coreImpl->protocol()->specName()); + + if (!spec) + return std::unexpected("can't send: hyprpaper doesn't have the spec?!"); + + if (spec->specVer() < 2) + return std::unexpected("can't send: hyprpaper protocol version too low (hyprpaper too old)"); + + auto manager = makeShared(socket->bindProtocol(g_coreImpl->protocol(), std::min(PROTOCOL_VERSION_SUPPORTED, spec->specVer()))); + + if (!manager) + return std::unexpected("wire error: couldn't create manager"); + + auto status = makeShared(manager->sendGetStatusObject()); + + status->setActiveWallpaper([](const char* mon, const char* wp) { std::println("{}: {}", mon, wp); }); + + socket->roundtrip(); + + return {}; +} + +std::expected Hyprpaper::makeHyprpaperRequest(const std::string_view& rq) { + if (!rq.contains(' ')) + return std::unexpected("Invalid request"); + + if (!rq.starts_with("/hyprpaper ")) + return std::unexpected("Invalid request"); + + std::string_view LHS, RHS; + auto spacePos = rq.find(' ', 12); + LHS = rq.substr(11, spacePos - 11); + RHS = rq.substr(spacePos + 1); + + if (LHS == "wallpaper") + return doWallpaper(RHS); + else if (LHS == "listactive") + return doListActive(); + else + return std::unexpected("invalid hyprpaper request"); + + return {}; +}