diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp
index d2006fcc4..827888b89 100644
--- a/include/modules/hyprland/workspaces.hpp
+++ b/include/modules/hyprland/workspaces.hpp
@@ -68,7 +68,7 @@ class Workspace {
   int id() const { return m_id; };
   std::string name() const { return m_name; };
   std::string output() const { return m_output; };
-  bool isActive() const { return m_active; };
+  bool isActive() const { return m_isActive; };
   bool isSpecial() const { return m_isSpecial; };
   bool isPersistent() const { return m_isPersistent; };
   bool isVisible() const { return m_isVisible; };
@@ -76,7 +76,7 @@ class Workspace {
   bool isUrgent() const { return m_isUrgent; };
 
   bool handleClicked(GdkEventButton* bt) const;
-  void setActive(bool value = true) { m_active = value; };
+  void setActive(bool value = true) { m_isActive = value; };
   void setPersistent(bool value = true) { m_isPersistent = value; };
   void setUrgent(bool value = true) { m_isUrgent = value; };
   void setVisible(bool value = true) { m_isVisible = value; };
@@ -99,7 +99,7 @@ class Workspace {
   std::string m_name;
   std::string m_output;
   uint m_windows;
-  bool m_active = false;
+  bool m_isActive = false;
   bool m_isSpecial = false;
   bool m_isPersistent = false;
   bool m_isUrgent = false;
@@ -135,8 +135,8 @@ class Workspaces : public AModule, public EventHandler {
   void onEvent(const std::string& e) override;
   void updateWindowCount();
   void sortWorkspaces();
-  void createWorkspace(Json::Value const& workspace_data,
-                       Json::Value const& clients_data = Json::Value::nullRef);
+  void createWorkspace(Json::Value const& workspaceData,
+                       Json::Value const& clientsData = Json::Value::nullRef);
   void removeWorkspace(std::string const& name);
   void setUrgentWorkspace(std::string const& windowaddress);
   void parseConfig(const Json::Value& config);
@@ -160,16 +160,24 @@ class Workspaces : public AModule, public EventHandler {
 
   void onWindowTitleEvent(std::string const& payload);
 
+  void onConfigReloaded();
+
   int windowRewritePriorityFunction(std::string const& window_rule);
 
   void doUpdate();
 
   void extendOrphans(int workspaceId, Json::Value const& clientsJson);
-  void registerOrphanWindow(WindowCreationPayload create_window_paylod);
+  void registerOrphanWindow(WindowCreationPayload create_window_payload);
+
+  void initializeWorkspaces();
+  void setCurrentMonitorId();
+  void loadPersistentWorkspacesFromConfig(Json::Value const& clientsJson);
+  void loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& clientsJson);
 
   bool m_allOutputs = false;
   bool m_showSpecial = false;
   bool m_activeOnly = false;
+  Json::Value m_persistentWorkspaceConfig;
 
   // Map for windows stored in workspaces not present in the current bar.
   // This happens when the user has multiple monitors (hence, multiple bars)
@@ -184,11 +192,6 @@ class Workspaces : public AModule, public EventHandler {
                                                  {"NUMBER", SortMethod::NUMBER},
                                                  {"DEFAULT", SortMethod::DEFAULT}};
 
-  void fillPersistentWorkspaces();
-  void createPersistentWorkspaces();
-  std::vector<std::string> m_persistentWorkspacesToCreate;
-  bool m_persistentCreated = false;
-
   std::string m_format;
 
   std::map<std::string, std::string> m_iconsMap;
diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp
index 88b5e135d..96893179f 100644
--- a/src/modules/hyprland/workspaces.cpp
+++ b/src/modules/hyprland/workspaces.cpp
@@ -49,6 +49,7 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
     gIPC = std::make_unique<IPC>();
   }
 
+  setCurrentMonitorId();
   init();
   registerIpc();
 }
@@ -64,7 +65,6 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
     for (std::string &name : formatIcons.getMemberNames()) {
       m_iconsMap.emplace(name, formatIcons[name].asString());
     }
-
     m_iconsMap.emplace("", "");
   }
 
@@ -112,11 +112,26 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
     }
   }
 
+  if (config_["persistent_workspaces"].isObject()) {
+    spdlog::warn(
+        "persistent_workspaces is deprecated. Please change config to use persistent-workspaces.");
+  }
+
+  if (config_["persistent-workspaces"].isObject() || config_["persistent_workspaces"].isObject()) {
+    m_persistentWorkspaceConfig = config_["persistent-workspaces"].isObject()
+                                      ? config_["persistent-workspaces"]
+                                      : config_["persistent_workspaces"];
+  }
+
   const Json::Value &formatWindowSeparator = config["format-window-separator"];
   m_formatWindowSeparator =
       formatWindowSeparator.isString() ? formatWindowSeparator.asString() : " ";
 
   const Json::Value &windowRewrite = config["window-rewrite"];
+  if (!windowRewrite.isObject()) {
+    spdlog::debug("window-rewrite is not defined or is not an object, using default rules.");
+    return;
+  }
 
   const Json::Value &windowRewriteDefaultConfig = config["window-rewrite-default"];
   std::string windowRewriteDefault =
@@ -127,9 +142,9 @@ auto Workspaces::parseConfig(const Json::Value &config) -> void {
       [this](std::string &window_rule) { return windowRewritePriorityFunction(window_rule); });
 }
 
-void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_paylod) {
-  if (!create_window_paylod.isEmpty(*this)) {
-    m_orphanWindowMap[create_window_paylod.getAddress()] = create_window_paylod.repr(*this);
+void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_payload) {
+  if (!create_window_payload.isEmpty(*this)) {
+    m_orphanWindowMap[create_window_payload.getAddress()] = create_window_payload.repr(*this);
   }
 }
 
@@ -144,6 +159,7 @@ auto Workspaces::registerIpc() -> void {
   gIPC->registerForIPC("closewindow", this);
   gIPC->registerForIPC("movewindow", this);
   gIPC->registerForIPC("urgent", this);
+  gIPC->registerForIPC("configreloaded", this);
 
   if (windowRewriteConfigUsesTitle()) {
     spdlog::info(
@@ -175,6 +191,7 @@ void Workspaces::doUpdate() {
   m_workspacesToCreate.clear();
 
   // get all active workspaces
+  spdlog::trace("Getting active workspaces");
   auto monitors = gIPC->getSocket1JsonReply("monitors");
   std::vector<std::string> visibleWorkspaces;
   for (Json::Value &monitor : monitors) {
@@ -184,6 +201,7 @@ void Workspaces::doUpdate() {
     }
   }
 
+  spdlog::trace("Updating workspace states");
   for (auto &workspace : m_workspaces) {
     // active
     workspace->setActive(workspace->name() == m_activeWorkspaceName);
@@ -204,6 +222,7 @@ void Workspaces::doUpdate() {
     workspace->update(m_format, workspaceIcon);
   }
 
+  spdlog::trace("Updating window count");
   bool anyWindowCreated = false;
   std::vector<WindowCreationPayload> notCreated;
 
@@ -285,6 +304,8 @@ void Workspaces::onEvent(const std::string &ev) {
     onWorkspaceRenamed(payload);
   } else if (eventName == "windowtitle") {
     onWindowTitleEvent(payload);
+  } else if (eventName == "configreloaded") {
+    onConfigReloaded();
   }
 
   dp.emit();
@@ -302,22 +323,37 @@ void Workspaces::onWorkspaceDestroyed(std::string const &payload) {
 
 void Workspaces::onWorkspaceCreated(std::string const &workspaceName,
                                     Json::Value const &clientsData) {
-  const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces");
+  spdlog::debug("Workspace created: {}", workspaceName);
+  auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces");
 
   if (!isWorkspaceIgnored(workspaceName)) {
+    auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules");
     for (Json::Value workspaceJson : workspacesJson) {
       std::string name = workspaceJson["name"].asString();
-      if (name == workspaceName &&
-          (allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
-          (showSpecial() || !name.starts_with("special")) && !isDoubleSpecial(workspaceName)) {
-        m_workspacesToCreate.emplace_back(workspaceJson, clientsData);
-        break;
+      if (name == workspaceName) {
+        if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
+            (showSpecial() || !name.starts_with("special")) && !isDoubleSpecial(workspaceName)) {
+          for (Json::Value const &rule : workspaceRules) {
+            if (rule["workspaceString"].asString() == workspaceName) {
+              workspaceJson["persistent"] = rule["persistent"].asBool();
+              break;
+            }
+          }
+
+          m_workspacesToCreate.emplace_back(workspaceJson, clientsData);
+          break;
+        }
+      } else {
+        extendOrphans(workspaceJson["id"].asInt(), clientsData);
       }
     }
+  } else {
+    spdlog::trace("Not creating workspace because it is ignored: {}", workspaceName);
   }
 }
 
 void Workspaces::onWorkspaceMoved(std::string const &payload) {
+  spdlog::debug("Workspace moved: {}", payload);
   std::string workspaceName = payload.substr(0, payload.find(','));
   std::string monitorName = payload.substr(payload.find(',') + 1);
 
@@ -325,11 +361,13 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) {
     Json::Value clientsData = gIPC->getSocket1JsonReply("clients");
     onWorkspaceCreated(workspaceName, clientsData);
   } else {
+    spdlog::debug("Removing workspace because it was moved to another monitor: {}");
     onWorkspaceDestroyed(workspaceName);
   }
 }
 
 void Workspaces::onWorkspaceRenamed(std::string const &payload) {
+  spdlog::debug("Workspace renamed: {}", payload);
   std::string workspaceIdStr = payload.substr(0, payload.find(','));
   int workspaceId = workspaceIdStr == "special" ? -99 : std::stoi(workspaceIdStr);
   std::string newName = payload.substr(payload.find(',') + 1);
@@ -346,10 +384,12 @@ void Workspaces::onWorkspaceRenamed(std::string const &payload) {
 }
 
 void Workspaces::onMonitorFocused(std::string const &payload) {
+  spdlog::trace("Monitor focused: {}", payload);
   m_activeWorkspaceName = payload.substr(payload.find(',') + 1);
 }
 
 void Workspaces::onWindowOpened(std::string const &payload) {
+  spdlog::trace("Window opened: {}", payload);
   updateWindowCount();
   size_t lastCommaIdx = 0;
   size_t nextCommaIdx = payload.find(',');
@@ -369,6 +409,7 @@ void Workspaces::onWindowOpened(std::string const &payload) {
 }
 
 void Workspaces::onWindowClosed(std::string const &addr) {
+  spdlog::trace("Window closed: {}", addr);
   updateWindowCount();
   for (auto &workspace : m_workspaces) {
     if (workspace->closeWindow(addr)) {
@@ -378,6 +419,7 @@ void Workspaces::onWindowClosed(std::string const &addr) {
 }
 
 void Workspaces::onWindowMoved(std::string const &payload) {
+  spdlog::trace("Window moved: {}", payload);
   updateWindowCount();
   size_t lastCommaIdx = 0;
   size_t nextCommaIdx = payload.find(',');
@@ -416,6 +458,7 @@ void Workspaces::onWindowMoved(std::string const &payload) {
 }
 
 void Workspaces::onWindowTitleEvent(std::string const &payload) {
+  spdlog::trace("Window title changed: {}", payload);
   std::optional<std::function<void(WindowCreationPayload)>> inserter;
 
   // If the window was an orphan, rename it at the orphan's vector
@@ -459,6 +502,11 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) {
   }
 }
 
+void Workspaces::onConfigReloaded() {
+  spdlog::info("Hyprland config reloaded, reinitializing hyprland/workspaces module...");
+  init();
+}
+
 void Workspaces::updateWindowCount() {
   const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces");
   for (auto &workspace : m_workspaces) {
@@ -515,8 +563,11 @@ std::optional<std::string> Workspace::closeWindow(WindowAddress const &addr) {
 
 void Workspaces::createWorkspace(Json::Value const &workspace_data,
                                  Json::Value const &clients_data) {
-  // avoid recreating existing workspaces
   auto workspaceName = workspace_data["name"].asString();
+  spdlog::debug("Creating workspace {}, persistent: {}", workspaceName,
+                workspace_data["persistent"].asBool() ? "true" : "false");
+
+  // avoid recreating existing workspaces
   auto workspace = std::find_if(
       m_workspaces.begin(), m_workspaces.end(),
       [workspaceName](std::unique_ptr<Workspace> const &w) {
@@ -525,9 +576,8 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
       });
 
   if (workspace != m_workspaces.end()) {
-    if (workspace_data["persistent"].asBool() and !(*workspace)->isPersistent()) {
-      (*workspace)->setPersistent();
-    }
+    // don't recreate workspace, but update persistency if necessary
+    (*workspace)->setPersistent(workspace_data["persistent"].asBool());
     return;
   }
 
@@ -540,6 +590,7 @@ void Workspaces::createWorkspace(Json::Value const &workspace_data,
 }
 
 void Workspaces::removeWorkspace(std::string const &name) {
+  spdlog::debug("Removing workspace {}", name);
   auto workspace =
       std::find_if(m_workspaces.begin(), m_workspaces.end(), [&](std::unique_ptr<Workspace> &x) {
         return (name.starts_with("special:") && name.substr(8) == x->name()) || name == x->name();
@@ -551,7 +602,7 @@ void Workspaces::removeWorkspace(std::string const &name) {
   }
 
   if ((*workspace)->isPersistent()) {
-    // don't remove persistent workspaces, createWorkspace will take care of replacement
+    spdlog::trace("Not removing persistent workspace {}", name);
     return;
   }
 
@@ -559,94 +610,106 @@ void Workspaces::removeWorkspace(std::string const &name) {
   m_workspaces.erase(workspace);
 }
 
-void Workspaces::fillPersistentWorkspaces() {
-  if (config_["persistent_workspaces"].isObject()) {
-    spdlog::warn(
-        "persistent_workspaces is deprecated. Please change config to use persistent-workspaces.");
-  }
+Json::Value createPersistentWorkspaceData(std::string const &name, std::string const &monitor) {
+  spdlog::trace("Creating persistent workspace: {} on monitor {}", name, monitor);
+  Json::Value workspaceData;
+  try {
+    // numbered persistent workspaces get the name as ID
+    workspaceData["id"] = name == "special" ? -99 : std::stoi(name);
+  } catch (const std::exception &e) {
+    // named persistent workspaces start with ID=0
+    workspaceData["id"] = 0;
+  }
+  workspaceData["name"] = name;
+  workspaceData["monitor"] = monitor;
+  workspaceData["windows"] = 0;
+  workspaceData["persistent"] = true;
+  return workspaceData;
+}
 
-  if (config_["persistent-workspaces"].isObject() || config_["persistent_workspaces"].isObject()) {
-    const Json::Value persistentWorkspaces = config_["persistent-workspaces"].isObject()
-                                                 ? config_["persistent-workspaces"]
-                                                 : config_["persistent_workspaces"];
-    const std::vector<std::string> keys = persistentWorkspaces.getMemberNames();
-
-    for (const std::string &key : keys) {
-      // only add if either:
-      // 1. key is "*" and this monitor is not already defined in the config
-      // 2. key is the current monitor name
-      bool canCreate =
-          (key == "*" && std::find(keys.begin(), keys.end(), m_bar.output->name) == keys.end()) ||
-          key == m_bar.output->name;
-      const Json::Value &value = persistentWorkspaces[key];
-
-      if (value.isInt()) {
-        // value is a number => create that many workspaces for this monitor
-        if (canCreate) {
-          int amount = value.asInt();
-          spdlog::debug("Creating {} persistent workspaces for monitor {}", amount,
-                        m_bar.output->name);
-          for (int i = 0; i < amount; i++) {
-            m_persistentWorkspacesToCreate.emplace_back(
-                std::to_string(m_monitorId * amount + i + 1));
-          }
+void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const &clientsJson) {
+  spdlog::info("Loading persistent workspaces from Waybar config");
+  const std::vector<std::string> keys = m_persistentWorkspaceConfig.getMemberNames();
+  std::vector<std::string> persistentWorkspacesToCreate;
+
+  const std::string currentMonitor = m_bar.output->name;
+  const bool monitorInConfig = std::find(keys.begin(), keys.end(), currentMonitor) != keys.end();
+  for (const std::string &key : keys) {
+    // only add if either:
+    // 1. key is the current monitor name
+    // 2. key is "*" and this monitor is not already defined in the config
+    bool canCreate = key == currentMonitor || (key == "*" && !monitorInConfig);
+    const Json::Value &value = m_persistentWorkspaceConfig[key];
+    spdlog::trace("Parsing persistent workspace config: {} => {}", key, value.toStyledString());
+
+    if (value.isInt()) {
+      // value is a number => create that many workspaces for this monitor
+      if (canCreate) {
+        int amount = value.asInt();
+        spdlog::debug("Creating {} persistent workspaces for monitor {}", amount, currentMonitor);
+        for (int i = 0; i < amount; i++) {
+          persistentWorkspacesToCreate.emplace_back(std::to_string(m_monitorId * amount + i + 1));
         }
-      } else if (value.isArray() && !value.empty()) {
-        // value is an array => create defined workspaces for this monitor
-        if (canCreate) {
-          for (const Json::Value &workspace : value) {
-            if (workspace.isInt()) {
-              spdlog::debug("Creating workspace {} on monitor {}", workspace, m_bar.output->name);
-              m_persistentWorkspacesToCreate.emplace_back(std::to_string(workspace.asInt()));
-            }
-          }
-        } else {
-          // key is the workspace and value is array of monitors to create on
-          for (const Json::Value &monitor : value) {
-            if (monitor.isString() && monitor.asString() == m_bar.output->name) {
-              m_persistentWorkspacesToCreate.emplace_back(key);
-              break;
-            }
+      }
+    } else if (value.isArray() && !value.empty()) {
+      // value is an array => create defined workspaces for this monitor
+      if (canCreate) {
+        for (const Json::Value &workspace : value) {
+          if (workspace.isInt()) {
+            spdlog::debug("Creating workspace {} on monitor {}", workspace, currentMonitor);
+            persistentWorkspacesToCreate.emplace_back(std::to_string(workspace.asInt()));
           }
         }
       } else {
-        // this workspace should be displayed on all monitors
-        m_persistentWorkspacesToCreate.emplace_back(key);
+        // key is the workspace and value is array of monitors to create on
+        for (const Json::Value &monitor : value) {
+          if (monitor.isString() && monitor.asString() == currentMonitor) {
+            persistentWorkspacesToCreate.emplace_back(currentMonitor);
+            break;
+          }
+        }
       }
+    } else {
+      // this workspace should be displayed on all monitors
+      persistentWorkspacesToCreate.emplace_back(key);
     }
   }
-}
 
-void Workspaces::createPersistentWorkspaces() {
-  for (const std::string &workspaceName : m_persistentWorkspacesToCreate) {
-    Json::Value newWorkspace;
-    try {
-      // numbered persistent workspaces get the name as ID
-      newWorkspace["id"] = workspaceName == "special" ? -99 : std::stoi(workspaceName);
-    } catch (const std::exception &e) {
-      // named persistent workspaces start with ID=0
-      newWorkspace["id"] = 0;
-    }
-    newWorkspace["name"] = workspaceName;
-    newWorkspace["monitor"] = m_bar.output->name;
-    newWorkspace["windows"] = 0;
-    newWorkspace["persistent"] = true;
-
-    createWorkspace(newWorkspace);
+  for (auto const &workspace : persistentWorkspacesToCreate) {
+    auto const workspaceData = createPersistentWorkspaceData(workspace, m_bar.output->name);
+    m_workspacesToCreate.emplace_back(workspaceData, clientsJson);
   }
 }
 
-void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson) {
-  for (const auto &client : clientsJson) {
-    if (client["workspace"]["id"].asInt() == workspaceId) {
-      registerOrphanWindow({client});
+void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value &clientsJson) {
+  spdlog::info("Loading persistent workspaces from Hyprland workspace rules");
+
+  auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules");
+  for (Json::Value const &rule : workspaceRules) {
+    if (!rule["workspaceString"].isString()) {
+      spdlog::warn("Workspace rules: invalid workspaceString, skipping: {}", rule);
+      continue;
+    }
+    if (!rule["persistent"].asBool()) {
+      continue;
+    }
+    auto const &workspace = rule["workspaceString"].asString();
+    auto const &monitor = rule["monitor"].asString();
+    // create this workspace persistently if:
+    // 1. the allOutputs config option is enabled
+    // 2. the rule's monitor is the current monitor
+    // 3. no monitor is specified in the rule => assume it needs to be persistent on every monitor
+    if (allOutputs() || m_bar.output->name == monitor || monitor.empty()) {
+      // => persistent workspace should be shown on this monitor
+      auto workspaceData = createPersistentWorkspaceData(workspace, m_bar.output->name);
+      m_workspacesToCreate.emplace_back(workspaceData, clientsJson);
+    } else {
+      m_workspacesToRemove.emplace_back(workspace);
     }
   }
 }
 
-void Workspaces::init() {
-  m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
-
+void Workspaces::setCurrentMonitorId() {
   // get monitor ID from name (used by persistent workspaces)
   m_monitorId = 0;
   auto monitors = gIPC->getSocket1JsonReply("monitors");
@@ -657,29 +720,58 @@ void Workspaces::init() {
     spdlog::error("Monitor '{}' does not have an ID? Using 0", m_bar.output->name);
   } else {
     m_monitorId = (*currentMonitor)["id"].asInt();
+    spdlog::trace("Current monitor ID: {}", m_monitorId);
   }
+}
 
-  const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces");
-  const Json::Value clientsJson = gIPC->getSocket1JsonReply("clients");
+void Workspaces::initializeWorkspaces() {
+  spdlog::debug("Initializing workspaces");
+
+  // if the workspace rules changed since last initialization, make sure we reset everything:
+  for (auto &workspace : m_workspaces) {
+    m_workspacesToRemove.push_back(workspace->name());
+  }
+
+  // get all current workspaces
+  auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces");
+  auto const clientsJson = gIPC->getSocket1JsonReply("clients");
 
   for (Json::Value workspaceJson : workspacesJson) {
     std::string workspaceName = workspaceJson["name"].asString();
     if ((allOutputs() || m_bar.output->name == workspaceJson["monitor"].asString()) &&
         (!workspaceName.starts_with("special") || showSpecial()) &&
         !isWorkspaceIgnored(workspaceName)) {
-      createWorkspace(workspaceJson, clientsJson);
+      m_workspacesToCreate.emplace_back(workspaceJson, clientsJson);
     } else {
       extendOrphans(workspaceJson["id"].asInt(), clientsJson);
     }
   }
 
-  fillPersistentWorkspaces();
-  createPersistentWorkspaces();
+  spdlog::debug("Initializing persistent workspaces");
+  if (m_persistentWorkspaceConfig.isObject()) {
+    // a persistent workspace config is defined, so use that instead of workspace rules
+    loadPersistentWorkspacesFromConfig(clientsJson);
+  } else {
+    // no persistent workspaces config defined, use Hyprland's workspace rules
+    loadPersistentWorkspacesFromWorkspaceRules(clientsJson);
+  }
+}
 
-  updateWindowCount();
+void Workspaces::extendOrphans(int workspaceId, Json::Value const &clientsJson) {
+  spdlog::trace("Extending orphans with workspace {}", workspaceId);
+  for (const auto &client : clientsJson) {
+    if (client["workspace"]["id"].asInt() == workspaceId) {
+      registerOrphanWindow({client});
+    }
+  }
+}
 
-  sortWorkspaces();
+void Workspaces::init() {
+  m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
 
+  initializeWorkspaces();
+  updateWindowCount();
+  sortWorkspaces();
   dp.emit();
 }
 
@@ -696,7 +788,8 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma
       m_name(workspace_data["name"].asString()),
       m_output(workspace_data["monitor"].asString()),  // TODO:allow using monitor desc
       m_windows(workspace_data["windows"].asInt()),
-      m_active(true) {
+      m_isActive(true),
+      m_isPersistent(workspace_data["persistent"].asBool()) {
   if (m_name.starts_with("name:")) {
     m_name = m_name.substr(5);
   } else if (m_name.starts_with("special")) {
@@ -704,10 +797,6 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma
     m_isSpecial = true;
   }
 
-  if (workspace_data.isMember("persistent")) {
-    m_isPersistent = workspace_data["persistent"].asBool();
-  }
-
   m_button.add_events(Gdk::BUTTON_PRESS_MASK);
   m_button.signal_button_press_event().connect(sigc::mem_fun(*this, &Workspace::handleClicked),
                                                false);
@@ -813,8 +902,7 @@ void Workspaces::sortWorkspaces() {
                     if (a->id() == -99 || b->id() == -99) {
                       return b->id() == -99;
                     }
-                    // both are 0 (not yet named persistents) / both are named specials (-98 <= ID
-                    // <=-1)
+                    // both are 0 (not yet named persistents) / named specials (-98 <= ID <= -1)
                     return isNameLess;
                   }
 
@@ -833,6 +921,7 @@ void Workspaces::sortWorkspaces() {
 }
 
 std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map) {
+  spdlog::trace("Selecting icon for workspace {}", name());
   if (isUrgent()) {
     auto urgentIconIt = icons_map.find("urgent");
     if (urgentIconIt != icons_map.end()) {
@@ -889,21 +978,19 @@ std::string &Workspace::selectIcon(std::map<std::string, std::string> &icons_map
 }
 
 bool Workspace::handleClicked(GdkEventButton *bt) const {
-  if (bt->type == GDK_BUTTON_PRESS) {
-    try {
-      if (id() > 0) {  // normal or numbered persistent
-        gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
-      } else if (!isSpecial()) {  // named
-        gIPC->getSocket1Reply("dispatch workspace name:" + name());
-      } else if (id() != -99) {  // named special
-        gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
-      } else {  // special
-        gIPC->getSocket1Reply("dispatch togglespecialworkspace");
-      }
-      return true;
-    } catch (const std::exception &e) {
-      spdlog::error("Failed to dispatch workspace: {}", e.what());
+  try {
+    if (id() > 0) {  // normal
+      gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id()));
+    } else if (!isSpecial()) {  // named (this includes persistent)
+      gIPC->getSocket1Reply("dispatch workspace name:" + name());
+    } else if (id() != -99) {  // named special
+      gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name());
+    } else {  // special
+      gIPC->getSocket1Reply("dispatch togglespecialworkspace");
     }
+    return true;
+  } catch (const std::exception &e) {
+    spdlog::error("Failed to dispatch workspace: {}", e.what());
   }
   return false;
 }
diff --git a/src/util/regex_collection.cpp b/src/util/regex_collection.cpp
index df0879c18..704d65455 100644
--- a/src/util/regex_collection.cpp
+++ b/src/util/regex_collection.cpp
@@ -66,4 +66,4 @@ std::string& RegexCollection::get(std::string& value) {
   return get(value, matched_any);
 }
 
-}  // namespace waybar::util
\ No newline at end of file
+}  // namespace waybar::util