#pragma once #include #include #include #include #include #include #include #include #include #include class HyprSocketHelper { public: static std::string getHyprlandSocketPath() { const char *hyprlandInstanceSignature = std::getenv("HYPRLAND_INSTANCE_SIGNATURE"); const char *xdgRuntimeDir = std::getenv("XDG_RUNTIME_DIR"); if (!xdgRuntimeDir || !hyprlandInstanceSignature) { return std::string(); } std::string basePath = std::string(xdgRuntimeDir) + "/hypr/" + std::string(hyprlandInstanceSignature) + "/"; std::string sock1 = basePath + ".socket2.sock"; if (access(sock1.c_str(), F_OK) == 0) { return sock1; } return std::string(); } static std::string getHyprlandCommandSocketPath() { const char *hyprlandInstanceSignature = std::getenv("HYPRLAND_INSTANCE_SIGNATURE"); const char *xdgRuntimeDir = std::getenv("XDG_RUNTIME_DIR"); if (!xdgRuntimeDir || !hyprlandInstanceSignature) { return std::string(); } std::string basePath = std::string(xdgRuntimeDir) + "/hypr/" + std::string(hyprlandInstanceSignature) + "/"; std::string sock1 = basePath + ".socket.sock"; if (access(sock1.c_str(), F_OK) == 0) { return sock1; } return std::string(); } }; class HyprctlHelper { public: static std::string sendCommand(const std::string &command) { std::string socketPath = HyprSocketHelper::getHyprlandCommandSocketPath(); assert(!socketPath.empty() && "Failed to get Hyprland command socket path"); int socketFd = socket(AF_UNIX, SOCK_STREAM, 0); assert(socketFd != -1 && "Failed to create Hyprland command socket"); struct sockaddr_un addr{}; std::memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; auto sunPathSpan = std::span(addr.sun_path); std::ranges::fill(sunPathSpan, '\0'); constexpr size_t kMaxPathLength = sizeof(addr.sun_path) - 1; const size_t copyLength = std::min(socketPath.size(), kMaxPathLength); std::copy_n(socketPath.begin(), copyLength, sunPathSpan.begin()); auto *sockaddrPtr = static_cast(static_cast(&addr)); int result = connect(socketFd, sockaddrPtr, sizeof(addr)); assert(result != -1 && "Failed to connect to Hyprland command socket"); ssize_t bytesSent = send(socketFd, command.c_str(), command.size(), 0); assert(bytesSent != -1 && "Failed to send command to Hyprland socket"); shutdown(socketFd, SHUT_WR); std::string response; constexpr size_t kBufferSize = 4096; std::array buffer{}; while (true) { ssize_t bytesRead = recv(socketFd, buffer.data(), buffer.size(), 0); if (bytesRead <= 0) { break; } response.append(buffer.data(), static_cast(bytesRead)); } close(socketFd); return response; } static nlohmann::json getMonitorData() { std::string result = sendCommand("j/monitors"); assert(!result.empty() && "Failed to get monitor data from Hyprland socket"); auto json = nlohmann::json::parse(result); assert(json.is_array()); return json; } static nlohmann::json getWorkspaceData() { std::string result = sendCommand("j/workspaces"); assert(!result.empty() && "Failed to get workspace data from Hyprland socket"); auto json = nlohmann::json::parse(result); assert(json.is_array()); return json; } static nlohmann::json getClientData() { std::string result = sendCommand("j/clients"); assert(!result.empty() && "Failed to get client data from Hyprland socket"); auto json = nlohmann::json::parse(result); assert(json.is_array()); return json; } static void dispatchWorkspace(int workspaceNumber) { std::string command = "dispatch workspace " + std::to_string(workspaceNumber); sendCommand(command); } };