Improvements for Hyprland workspace

1. Utilize `m_mutex` to safeguard member fields of `hyprland::Workspaces` as they are modified by multiple threads, including the event listener thread and UI thread. This applies to all member fields, not just `m_workspacesToCreate`.

2. Tidy up the create/remove workspace code.
This commit is contained in:
yangyingchao 2024-01-05 13:49:11 +08:00
parent 4b20f522f0
commit a34e3ccc86
2 changed files with 20 additions and 22 deletions

View File

@ -161,6 +161,8 @@ class Workspaces : public AModule, public EventHandler {
int windowRewritePriorityFunction(std::string const& window_rule);
void doUpdate();
bool m_allOutputs = false;
bool m_showSpecial = false;
bool m_activeOnly = false;

View File

@ -4,11 +4,8 @@
#include <spdlog/spdlog.h>
#include <algorithm>
#include <charconv>
#include <memory>
#include <shared_mutex>
#include <string>
#include <thread>
#include <utility>
#include <variant>
@ -16,8 +13,6 @@
namespace waybar::modules::hyprland {
std::shared_mutex workspaceCreateSmtx;
int Workspaces::windowRewritePriorityFunction(std::string const &window_rule) {
// Rules that match against title are prioritized
// Rules that don't specify if they're matching against either title or class are deprioritized
@ -153,27 +148,26 @@ auto Workspaces::registerIpc() -> void {
}
}
auto Workspaces::update() -> void {
/**
* Workspaces::doUpdate - update workspaces in UI thread.
*
* Note: some memberfields are modified by both UI thread and event listener thread, use m_mutex to
* protect these member fields, and lock should released before calling AModule::update().
*/
void Workspaces::doUpdate() {
std::unique_lock lock(m_mutex);
// remove workspaces that wait to be removed
unsigned int currentRemoveWorkspaceNum = 0;
for (const std::string &workspaceToRemove : m_workspacesToRemove) {
removeWorkspace(workspaceToRemove);
currentRemoveWorkspaceNum++;
}
for (unsigned int i = 0; i < currentRemoveWorkspaceNum; i++) {
m_workspacesToRemove.erase(m_workspacesToRemove.begin());
for (auto &elem : m_workspacesToRemove) {
removeWorkspace(elem);
}
m_workspacesToRemove.clear();
// add workspaces that wait to be created
std::shared_lock<std::shared_mutex> workspaceCreateShareLock(workspaceCreateSmtx);
unsigned int currentCreateWorkspaceNum = 0;
for (Json::Value const &workspaceToCreate : m_workspacesToCreate) {
createWorkspace(workspaceToCreate);
currentCreateWorkspaceNum++;
}
for (unsigned int i = 0; i < currentCreateWorkspaceNum; i++) {
m_workspacesToCreate.erase(m_workspacesToCreate.begin());
for (auto &elem : m_workspacesToCreate) {
createWorkspace(elem);
}
m_workspacesToCreate.clear();
// get all active workspaces
auto monitors = gIPC->getSocket1JsonReply("monitors");
@ -231,7 +225,10 @@ auto Workspaces::update() -> void {
m_windowsToCreate.clear();
m_windowsToCreate = notCreated;
}
auto Workspaces::update() -> void {
doUpdate();
AModule::update();
}
@ -305,7 +302,6 @@ void Workspaces::onWorkspaceCreated(std::string const &payload) {
if (name == payload &&
(allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
(showSpecial() || !name.starts_with("special")) && !isDoubleSpecial(payload)) {
std::unique_lock<std::shared_mutex> workspaceCreateUniqueLock(workspaceCreateSmtx);
m_workspacesToCreate.push_back(workspaceJson);
break;
}