Workspaces: Optimize GetStatus

We previously called DispatchIPC 18 times every 100ms
Now it is only 2 times per 100ms
This commit is contained in:
scorpion-26 2023-02-24 13:23:34 +01:00
parent d2d66171df
commit 38116636ae
4 changed files with 91 additions and 46 deletions

View file

@ -202,9 +202,10 @@ namespace Bar
static std::array<Button*, 9> workspaces; static std::array<Button*, 9> workspaces;
TimerResult UpdateWorkspaces(Box&) TimerResult UpdateWorkspaces(Box&)
{ {
System::PollWorkspaces((uint32_t)monitorID, workspaces.size());
for (size_t i = 0; i < workspaces.size(); i++) for (size_t i = 0; i < workspaces.size(); i++)
{ {
switch (System::GetWorkspaceStatus((uint32_t)monitorID, i + 1)) switch (System::GetWorkspaceStatus(i + 1))
{ {
case System::WorkspaceStatus::Dead: workspaces[i]->SetClass("ws-dead"); break; case System::WorkspaceStatus::Dead: workspaces[i]->SetClass("ws-dead"); break;
case System::WorkspaceStatus::Inactive: workspaces[i]->SetClass("ws-inactive"); break; case System::WorkspaceStatus::Inactive: workspaces[i]->SetClass("ws-inactive"); break;

View file

@ -55,54 +55,93 @@ namespace Hyprland
return res; return res;
} }
inline System::WorkspaceStatus GetStatus(uint32_t monitorID, uint32_t workspaceId) static std::vector<System::WorkspaceStatus> workspaceStati;
inline void PollStatus(uint32_t monitorID, uint32_t numWorkspaces)
{
if (RuntimeConfig::Get().hasHyprland == false)
{
LOG("Error: Polled workspace status, but Hyprland isn't open!");
return;
}
workspaceStati.clear();
workspaceStati.resize(numWorkspaces, System::WorkspaceStatus::Dead);
size_t parseIdx = 0;
// First parse workspaces
std::string workspaces = DispatchIPC("/workspaces");
while ((parseIdx = workspaces.find("workspace ID ", parseIdx)) != std::string::npos)
{
// Goto (
size_t begWSNum = workspaces.find('(', parseIdx) + 1;
size_t endWSNum = workspaces.find(')', begWSNum);
std::string ws = workspaces.substr(begWSNum, endWSNum - begWSNum);
int32_t wsId = std::atoi(ws.c_str());
if (wsId >= 1 && wsId < (int32_t)numWorkspaces)
{
// WS is at least inactive
workspaceStati[wsId - 1] = System::WorkspaceStatus::Inactive;
}
parseIdx = endWSNum;
}
// Parse active workspaces for monitor
std::string monitors = DispatchIPC("/monitors");
parseIdx = 0;
while ((parseIdx = monitors.find("Monitor ", parseIdx)) != std::string::npos)
{
// Goto ( and remove ID (=Advance 4 spaces, 1 for (, two for ID, one for space)
size_t begMonNum = monitors.find('(', parseIdx) + 4;
size_t endMonNum = monitors.find(')', begMonNum);
std::string mon = monitors.substr(begMonNum, endMonNum - begMonNum);
int32_t monIdx = std::atoi(mon.c_str());
// Parse active workspace
parseIdx = monitors.find("active workspace: ", parseIdx);
ASSERT(parseIdx != std::string::npos, "Invalid IPC response!");
size_t begWSNum = monitors.find('(', parseIdx) + 1;
size_t endWSNum = monitors.find(')', begWSNum);
std::string ws = monitors.substr(begWSNum, endWSNum - begWSNum);
int32_t wsId = std::atoi(ws.c_str());
// Check if focused
parseIdx = monitors.find("focused: ", parseIdx);
ASSERT(parseIdx != std::string::npos, "Invalid IPC response!");
size_t begFocused = monitors.find(' ', parseIdx) + 1;
size_t endFocused = monitors.find('\n', begFocused);
bool focused = std::string_view(monitors).substr(begFocused, endFocused - begFocused) == "yes";
if (wsId >= 1 && wsId < (int32_t)numWorkspaces)
{
if ((uint32_t)monIdx == monitorID)
{
if (focused)
{
workspaceStati[wsId - 1] = System::WorkspaceStatus::Active;
}
else
{
workspaceStati[wsId - 1] = System::WorkspaceStatus::Current;
}
}
else
{
workspaceStati[wsId - 1] = System::WorkspaceStatus::Visible;
}
}
}
}
inline System::WorkspaceStatus GetStatus(uint32_t workspaceId)
{ {
if (RuntimeConfig::Get().hasHyprland == false) if (RuntimeConfig::Get().hasHyprland == false)
{ {
LOG("Error: Queried for workspace status, but Hyprland isn't open!"); LOG("Error: Queried for workspace status, but Hyprland isn't open!");
return System::WorkspaceStatus::Dead; return System::WorkspaceStatus::Dead;
} }
ASSERT(workspaceId > 0 && workspaceId <= workspaceStati.size(), "Invalid workspaceId, you need to poll the workspace first!");
std::string workspaces = DispatchIPC("/workspaces"); return workspaceStati[workspaceId - 1];
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) inline void Goto(uint32_t workspace)

View file

@ -447,9 +447,13 @@ namespace System
} }
#ifdef WITH_HYPRLAND #ifdef WITH_HYPRLAND
WorkspaceStatus GetWorkspaceStatus(uint32_t monitor, uint32_t workspace) void PollWorkspaces(uint32_t monitor, uint32_t numWorkspaces)
{ {
return Hyprland::GetStatus(monitor, workspace); Hyprland::PollStatus(monitor, numWorkspaces);
}
WorkspaceStatus GetWorkspaceStatus(uint32_t workspace)
{
return Hyprland::GetStatus(workspace);
} }
void GotoWorkspace(uint32_t workspace) void GotoWorkspace(uint32_t workspace)
{ {

View file

@ -92,7 +92,8 @@ namespace System
Current, Current,
Active Active
}; };
WorkspaceStatus GetWorkspaceStatus(uint32_t monitor, uint32_t workspace); void PollWorkspaces(uint32_t monitor, uint32_t numWorkspaces);
WorkspaceStatus GetWorkspaceStatus(uint32_t workspace);
void GotoWorkspace(uint32_t workspace); void GotoWorkspace(uint32_t workspace);
// direction: + or - // direction: + or -
void GotoNextWorkspace(char direction); void GotoNextWorkspace(char direction);