gBar/src/Hyprland.h
scorpion-26 812e689c77 Disable opt. dependencies dynamically
This lifts the requirement of needing to disable the dependencies by
hand if you don't have them installed.
It also enables us to have a single package, that works for all.
2023-01-30 16:58:38 +01:00

119 lines
3.9 KiB
C++

#pragma once
#include "Common.h"
#include "System.h"
#include "Config.h"
#include <cstdint>
#include <string>
#include <cstdlib>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#ifdef WITH_HYPRLAND
namespace Hyprland
{
inline void Init()
{
if (!getenv("HYPRLAND_INSTANCE_SIGNATURE"))
{
LOG("Hyprland not running, disabling workspaces");
// Not available
RuntimeConfig::Get().hasHyprland = false;
}
}
inline std::string DispatchIPC(const std::string& arg)
{
int hyprSocket = socket(AF_UNIX, SOCK_STREAM, 0);
const char* instanceSignature = getenv("HYPRLAND_INSTANCE_SIGNATURE");
std::string socketPath = "/tmp/hypr/" + std::string(instanceSignature) + "/.socket.sock";
sockaddr_un addr = {};
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path));
int ret = connect(hyprSocket, (sockaddr*)&addr, SUN_LEN(&addr));
ASSERT(ret >= 0, "Couldn't connect to hyprland socket");
ssize_t written = write(hyprSocket, arg.c_str(), arg.size());
ASSERT(written >= 0, "Couldn't write to socket");
char buf[2056];
std::string res;
while (true)
{
ssize_t bytesRead = read(hyprSocket, buf, sizeof(buf));
if (bytesRead == 0)
{
break;
}
ASSERT(bytesRead >= 0, "Couldn't read");
res += std::string(buf, bytesRead);
}
close(hyprSocket);
return res;
}
inline System::WorkspaceStatus GetStatus(uint32_t monitorID, uint32_t workspaceId)
{
if (RuntimeConfig::Get().hasHyprland == false)
{
LOG("Error: Queried for workspace status, but Hyprland isn't open!");
return System::WorkspaceStatus::Dead;
}
std::string workspaces = DispatchIPC("/workspaces");
if (workspaces.find("workspace ID " + std::to_string(workspaceId)) == std::string::npos)
{
// It's dead and there's nothing I can do about it
// [Doesn't exist, no need to check anything else]
return System::WorkspaceStatus::Dead;
}
std::string monitors = DispatchIPC("/monitors");
size_t beginMonitor = monitors.find("(ID " + std::to_string(monitorID) + ")");
ASSERT(beginMonitor != std::string::npos, "Monitor not found!");
size_t endMonitor = monitors.find("dpmsStatus", beginMonitor);
std::string_view selectedMon = std::string_view(monitors).substr(beginMonitor, endMonitor - beginMonitor);
size_t activeWorkspaceLoc = selectedMon.find("active workspace:");
size_t workspaceBeg = selectedMon.find("(", activeWorkspaceLoc);
size_t workspaceEnd = selectedMon.find(")", workspaceBeg);
std::string workspaceNum = std::string(selectedMon.substr(workspaceBeg + 1, workspaceEnd - workspaceBeg - 1));
// Active workspace
if (std::stoi(workspaceNum) == (int)workspaceId)
{
// Check if focused
if (selectedMon.find("focused: yes") != std::string::npos)
{
return System::WorkspaceStatus::Active;
}
else
{
return System::WorkspaceStatus::Current;
}
}
if (monitors.find("active workspace: " + std::to_string(workspaceId)) != std::string::npos)
{
return System::WorkspaceStatus::Visible;
}
else
{
return System::WorkspaceStatus::Inactive;
}
}
inline void Goto(uint32_t workspace)
{
if (RuntimeConfig::Get().hasHyprland == false)
{
LOG("Error: Called Go to workspace, but Hyprland isn't open!");
return;
}
system(("hyprctl dispatch workspace " + std::to_string(workspace)).c_str());
}
}
#endif