From fae1913f6c533d5517c9e371b1e33714706d4417 Mon Sep 17 00:00:00 2001 From: scorpion-26 Date: Thu, 1 Aug 2024 22:58:11 +0200 Subject: [PATCH] Add option to hide trailing workspaces Potentially implements https://github.com/scorpion-26/gBar/issues/106 --- data/config | 3 +++ src/Bar.cpp | 7 +++++++ src/Config.cpp | 1 + src/Config.h | 3 ++- src/System.cpp | 4 ++++ src/System.h | 1 + src/Workspaces.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/Workspaces.h | 2 ++ 8 files changed, 56 insertions(+), 1 deletion(-) diff --git a/data/config b/data/config index 0e87922..130ce82 100644 --- a/data/config +++ b/data/config @@ -94,6 +94,9 @@ WorkspaceScrollInvert: false # Number of workspaces to display. Displayed workspace IDs are 1-n (Default: 1-9) NumWorkspaces: 9 +# Hide trailing unused workspaces (by ID). A workspace is considered unused, if it has no window on it +WorkspaceHideUnused: true + # Use Hyprland IPC instead of the ext_workspace protocol for workspace polling. # Hyprland IPC is *slightly* less performant (+0.1% one core), but way less bug prone, # since the protocol is not as feature complete as Hyprland IPC. diff --git a/src/Bar.cpp b/src/Bar.cpp index 8a5b331..a0bdc06 100644 --- a/src/Bar.cpp +++ b/src/Bar.cpp @@ -450,8 +450,15 @@ namespace Bar TimerResult UpdateWorkspaces(Box&) { System::PollWorkspaces(monitor, workspaces.size()); + uint32_t maxWorkspace = Config::Get().workspaceHideUnused ? System::GetMaxUsedWorkspace() : 0; for (size_t i = 0; i < workspaces.size(); i++) { + if (Config::Get().workspaceHideUnused) + { + // Only show ws's, who are before the max used ws + workspaces[i]->SetVisible(i < maxWorkspace); + } + switch (System::GetWorkspaceStatus(i + 1)) { case System::WorkspaceStatus::Dead: workspaces[i]->SetClass("ws-dead"); break; diff --git a/src/Config.cpp b/src/Config.cpp index f06e698..e5e15f8 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -292,6 +292,7 @@ void Config::Load(const std::string& overrideConfigLocation) AddConfigVar("NetworkWidget", config.networkWidget, lineView, foundProperty); AddConfigVar("WorkspaceScrollOnMonitor", config.workspaceScrollOnMonitor, lineView, foundProperty); AddConfigVar("WorkspaceScrollInvert", config.workspaceScrollInvert, lineView, foundProperty); + AddConfigVar("WorkspaceHideUnused", config.workspaceHideUnused, lineView, foundProperty); AddConfigVar("UseHyprlandIPC", config.useHyprlandIPC, lineView, foundProperty); AddConfigVar("EnableSNI", config.enableSNI, lineView, foundProperty); AddConfigVar("SensorTooltips", config.sensorTooltips, lineView, foundProperty); diff --git a/src/Config.h b/src/Config.h index 94e8eae..b8f3276 100644 --- a/src/Config.h +++ b/src/Config.h @@ -13,7 +13,7 @@ public: std::vector widgetsRight = {"Tray", "Packages", "Audio", "Bluetooth", "Network", "Disk", "VRAM", "GPU", "RAM", "CPU", "Battery", "Power"}; - std::string cpuThermalZone = ""; // idk, no standard way of doing this. + std::string cpuThermalZone = ""; // idk, no standard way of doing this. std::string amdGpuThermalZone = "/device/hwmon/hwmon1/temp1_input"; std::string networkAdapter = "eno1"; // Is this standard? std::string drmAmdCard = "card0"; // The card to poll in AMDGPU. @@ -63,6 +63,7 @@ public: bool networkWidget = true; bool workspaceScrollOnMonitor = true; // Scroll through workspaces on monitor instead of all bool workspaceScrollInvert = false; // Up = +1, instead of Up = -1 + bool workspaceHideUnused = false; // Only display necessary workspaces (i.e. trailing empty workspaces) bool useHyprlandIPC = true; // Use Hyprland IPC instead of ext_workspaces protocol (Less buggy, but also less performant) bool enableSNI = true; // Enable tray icon bool sensorTooltips = false; // Use tooltips instead of sliders for the sensors diff --git a/src/System.cpp b/src/System.cpp index 3150d34..f38ea09 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -502,6 +502,10 @@ namespace System { return Workspaces::GetStatus(workspace); } + uint32_t GetMaxUsedWorkspace() + { + return Workspaces::GetMaxUsedWorkspace(); + } void GotoWorkspace(uint32_t workspace) { return Workspaces::Goto(workspace); diff --git a/src/System.h b/src/System.h index 50d7efa..6325a52 100644 --- a/src/System.h +++ b/src/System.h @@ -99,6 +99,7 @@ namespace System }; void PollWorkspaces(const std::string& monitor, uint32_t numWorkspaces); WorkspaceStatus GetWorkspaceStatus(uint32_t workspace); + uint32_t GetMaxUsedWorkspace(); void GotoWorkspace(uint32_t workspace); // direction: + or - void GotoNextWorkspace(char direction); diff --git a/src/Workspaces.cpp b/src/Workspaces.cpp index b501689..26050bf 100644 --- a/src/Workspaces.cpp +++ b/src/Workspaces.cpp @@ -65,6 +65,18 @@ namespace Workspaces return System::WorkspaceStatus::Dead; } + uint32_t GetMaxUsedWorkspace() + { + uint32_t maxUsedWorkspace = 0; + for (auto& workspace : ::Wayland::GetWorkspaces()) + { + if (workspace.second.id > maxUsedWorkspace) + { + maxUsedWorkspace = workspace.second.id; + } + } + return maxUsedWorkspace; + } } #ifdef WITH_HYPRLAND @@ -169,6 +181,7 @@ namespace Workspaces } static std::vector workspaceStati; + static uint32_t maxUsedWorkspace = 0; void PollStatus(const std::string& monitor, uint32_t numWorkspaces) { @@ -179,6 +192,7 @@ namespace Workspaces } workspaceStati.clear(); workspaceStati.resize(numWorkspaces, System::WorkspaceStatus::Dead); + maxUsedWorkspace = 0; size_t parseIdx = 0; // First parse workspaces @@ -197,6 +211,9 @@ namespace Workspaces // WS is at least inactive workspaceStati[wsId - 1] = System::WorkspaceStatus::Inactive; } + // Update maxUsedWorkspace + if (wsId > 0 && (uint32_t)wsId > maxUsedWorkspace) + maxUsedWorkspace = wsId; parseIdx = endWSNum; } @@ -244,6 +261,9 @@ namespace Workspaces workspaceStati[wsId - 1] = System::WorkspaceStatus::Visible; } } + // Update maxUsedWorkspace + if (wsId > 0 && (uint32_t)wsId > maxUsedWorkspace) + maxUsedWorkspace = wsId; } } @@ -257,6 +277,11 @@ namespace Workspaces ASSERT(workspaceId > 0 && workspaceId <= workspaceStati.size(), "Invalid workspaceId, you need to poll the workspace first!"); return workspaceStati[workspaceId - 1]; } + + uint32_t GetMaxUsedWorkspace() + { + return maxUsedWorkspace; + } } #endif @@ -294,6 +319,17 @@ namespace Workspaces return Wayland::GetStatus(workspaceId); } + uint32_t GetMaxUsedWorkspace() + { +#ifdef WITH_HYPRLAND + if (Config::Get().useHyprlandIPC) + { + return Hyprland::GetMaxUsedWorkspace(); + } +#endif + return Wayland::GetMaxUsedWorkspace(); + } + void Shutdown() {} } #endif diff --git a/src/Workspaces.h b/src/Workspaces.h index 884ad11..2f8f2dc 100644 --- a/src/Workspaces.h +++ b/src/Workspaces.h @@ -20,6 +20,8 @@ namespace Workspaces System::WorkspaceStatus GetStatus(uint32_t workspaceId); + uint32_t GetMaxUsedWorkspace(); + void Shutdown(); // TODO: Use ext_workspaces for this, if applicable