133 lines
4.3 KiB
C++
133 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <nlohmann/json.hpp>
|
|
#include <span>
|
|
#include <string>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <unistd.h>
|
|
|
|
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<char, sizeof(addr.sun_path)>(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<struct sockaddr *>(static_cast<void *>(&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<char, kBufferSize> buffer{};
|
|
while (true) {
|
|
ssize_t bytesRead = recv(socketFd, buffer.data(), buffer.size(), 0);
|
|
if (bytesRead <= 0) {
|
|
break;
|
|
}
|
|
|
|
response.append(buffer.data(), static_cast<size_t>(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);
|
|
}
|
|
}; |