Skip to content

core: move workspace ptrs to weak #11194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,14 @@ set(CXX_STANDARD_REQUIRED ON)
add_compile_options(
-Wall
-Wextra
-Wpedantic
-Wno-unused-parameter
-Wno-unused-value
-Wno-missing-field-initializers
-Wno-gnu-zero-variadic-macro-arguments
-Wno-narrowing
-Wno-pointer-arith
-Wno-clobbered
-Wpedantic
-fmacro-prefix-map=${CMAKE_SOURCE_DIR}/=)

set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
Expand Down
44 changes: 15 additions & 29 deletions src/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,29 +1338,14 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) {
}

PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) {
for (auto const& w : m_workspaces) {
for (auto const& w : getWorkspaces()) {
if (w->m_id == id && !w->inert())
return w;
return w.lock();
}

return nullptr;
}

void CCompositor::sanityCheckWorkspaces() {
auto it = m_workspaces.begin();
while (it != m_workspaces.end()) {
const auto& WORKSPACE = *it;

// If ref == 1, only the compositor holds a ref, which means it's inactive and has no mapped windows.
if (!WORKSPACE->m_persistent && WORKSPACE.strongRef() == 1) {
it = m_workspaces.erase(it);
continue;
}

++it;
}
}

PHLWINDOW CCompositor::getUrgentWindow() {
for (auto const& w : m_windows) {
if (w->m_isMapped && w->m_isUrgent)
Expand Down Expand Up @@ -1732,7 +1717,7 @@ PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::op

WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
WORKSPACEID lowest = -1337 + 1;
for (auto const& w : m_workspaces) {
for (auto const& w : getWorkspaces()) {
if (w->m_id < -1 && w->m_id < lowest)
lowest = w->m_id;
}
Expand All @@ -1741,9 +1726,9 @@ WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
}

PHLWORKSPACE CCompositor::getWorkspaceByName(const std::string& name) {
for (auto const& w : m_workspaces) {
for (auto const& w : getWorkspaces()) {
if (w->m_name == name && !w->inert())
return w;
return w.lock();
}

return nullptr;
Expand Down Expand Up @@ -2144,7 +2129,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo
if (!SWITCHINGISACTIVE)
nextWorkspaceOnMonitorID = pWorkspace->m_id;
else {
for (auto const& w : m_workspaces) {
for (auto const& w : getWorkspaces()) {
if (w->m_monitor == POLDMON && w->m_id != pWorkspace->m_id && !w->m_isSpecialWorkspace) {
nextWorkspaceOnMonitorID = w->m_id;
break;
Expand Down Expand Up @@ -2258,7 +2243,7 @@ bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) {
WORKSPACEID lowestID = INT64_MAX;
WORKSPACEID highestID = INT64_MIN;

for (auto const& w : m_workspaces) {
for (auto const& w : getWorkspaces()) {
if (w->m_isSpecialWorkspace)
continue;
lowestID = std::min(w->m_id, lowestID);
Expand Down Expand Up @@ -2660,7 +2645,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO
return nullptr;
}

const auto PWORKSPACE = m_workspaces.emplace_back(CWorkspace::create(id, PMONITOR, NAME, SPECIAL, isEmpty));
const auto PWORKSPACE = CWorkspace::create(id, PMONITOR, NAME, SPECIAL, isEmpty);

PWORKSPACE->m_alpha->setValueAndWarp(0);

Expand Down Expand Up @@ -2694,15 +2679,19 @@ bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) {

WORKSPACEID CCompositor::getNewSpecialID() {
WORKSPACEID highest = SPECIAL_WORKSPACE_START;
for (auto const& ws : m_workspaces) {
if (ws->m_isSpecialWorkspace && ws->m_id > highest) {
for (auto const& ws : getWorkspaces()) {
if (ws->m_isSpecialWorkspace && ws->m_id > highest)
highest = ws->m_id;
}
}

return highest + 1;
}

void CCompositor::registerWorkspace(PHLWORKSPACE w) {
m_workspaces.emplace_back(w);
w->m_events.destroy.listenStatic([this, weak = PHLWORKSPACEREF{w}] { std::erase(m_workspaces, weak); });
}

void CCompositor::performUserChecks() {
static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
static auto PNOCHECKQTUTILS = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_qtutils_check");
Expand Down Expand Up @@ -3176,7 +3165,4 @@ void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspace
continue;
}
}

// cleanup old
sanityCheckWorkspaces();
}
43 changes: 26 additions & 17 deletions src/Compositor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <sys/resource.h>

#include <ranges>

#include "managers/XWaylandManager.hpp"
#include "managers/KeybindManager.hpp"
#include "managers/SessionLockManager.hpp"
Expand Down Expand Up @@ -42,7 +44,6 @@ class CCompositor {
std::vector<PHLMONITOR> m_realMonitors; // for all monitors, even those turned off
std::vector<PHLWINDOW> m_windows;
std::vector<PHLLS> m_layers;
std::vector<PHLWORKSPACE> m_workspaces;
std::vector<PHLWINDOWREF> m_windowsFadingOut;
std::vector<PHLLSREF> m_surfacesFadingOut;

Expand Down Expand Up @@ -75,6 +76,13 @@ class CCompositor {

// ------------------------------------------------- //

auto getWorkspaces() {
return std::views::filter(m_workspaces, [](const auto& e) { return e; });
}
void registerWorkspace(PHLWORKSPACE w);

//

PHLMONITOR getMonitorFromID(const MONITORID&);
PHLMONITOR getMonitorFromName(const std::string&);
PHLMONITOR getMonitorFromDesc(const std::string&);
Expand All @@ -96,7 +104,6 @@ class CCompositor {
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
PHLWORKSPACE getWorkspaceByName(const std::string&);
PHLWORKSPACE getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces();
PHLWINDOW getUrgentWindow();
bool isWindowActive(PHLWINDOW);
void changeWindowZOrder(PHLWINDOW, bool);
Expand Down Expand Up @@ -156,21 +163,23 @@ class CCompositor {
std::string m_explicitConfigPath;

private:
void initAllSignals();
void removeAllSignals();
void cleanEnvironment();
void setRandomSplash();
void initManagers(eManagersInitStage stage);
void prepareFallbackOutput();
void createLockFile();
void removeLockFile();
void setMallocThreshold();

bool m_bDrmSyncobjTimelineSupported = false;

uint64_t m_hyprlandPID = 0;
wl_event_source* m_critSigSource = nullptr;
rlimit m_originalNofile = {};
void initAllSignals();
void removeAllSignals();
void cleanEnvironment();
void setRandomSplash();
void initManagers(eManagersInitStage stage);
void prepareFallbackOutput();
void createLockFile();
void removeLockFile();
void setMallocThreshold();

bool m_bDrmSyncobjTimelineSupported = false;

uint64_t m_hyprlandPID = 0;
wl_event_source* m_critSigSource = nullptr;
rlimit m_originalNofile = {};

std::vector<PHLWORKSPACEREF> m_workspaces;
};

inline UP<CCompositor> g_pCompositor;
2 changes: 1 addition & 1 deletion src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
refreshGroupBarGradients();

// Updates dynamic window and workspace rules
for (auto const& w : g_pCompositor->m_workspaces) {
for (auto const& w : g_pCompositor->getWorkspaces()) {
if (w->inert())
continue;
w->updateWindows();
Expand Down
8 changes: 4 additions & 4 deletions src/debug/HyprCtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,16 +432,16 @@ static std::string workspacesRequest(eHyprCtlOutputFormat format, std::string re

if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "[";
for (auto const& w : g_pCompositor->m_workspaces) {
result += CHyprCtl::getWorkspaceData(w, format);
for (auto const& w : g_pCompositor->getWorkspaces()) {
result += CHyprCtl::getWorkspaceData(w.lock(), format);
result += ",";
}

trimTrailingComma(result);
result += "]";
} else {
for (auto const& w : g_pCompositor->m_workspaces) {
result += CHyprCtl::getWorkspaceData(w, format);
for (auto const& w : g_pCompositor->getWorkspaces()) {
result += CHyprCtl::getWorkspaceData(w.lock(), format);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/desktop/Workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ using namespace Hyprutils::String;
PHLWORKSPACE CWorkspace::create(WORKSPACEID id, PHLMONITOR monitor, std::string name, bool special, bool isEmpty) {
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitor, name, special, isEmpty);
workspace->init(workspace);
g_pCompositor->registerWorkspace(workspace);
return workspace;
}

Expand Down
6 changes: 3 additions & 3 deletions src/helpers/MiscFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
std::set<WORKSPACEID> invalidWSes;

// Collect all the workspaces we can't jump to.
for (auto const& ws : g_pCompositor->m_workspaces) {
for (auto const& ws : g_pCompositor->getWorkspaces()) {
if (ws->m_isSpecialWorkspace || (ws->m_monitor != g_pCompositor->m_lastMonitor)) {
// Can't jump to this workspace
invalidWSes.insert(ws->m_id);
Expand All @@ -237,7 +237,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {

// Prepare all named workspaces in case when we need them
std::vector<WORKSPACEID> namedWSes;
for (auto const& ws : g_pCompositor->m_workspaces) {
for (auto const& ws : g_pCompositor->getWorkspaces()) {
if (ws->m_isSpecialWorkspace || (ws->m_monitor != g_pCompositor->m_lastMonitor) || ws->m_id >= 0)
continue;

Expand Down Expand Up @@ -381,7 +381,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
int remains = (int)result.id;

std::vector<WORKSPACEID> validWSes;
for (auto const& ws : g_pCompositor->m_workspaces) {
for (auto const& ws : g_pCompositor->getWorkspaces()) {
if (ws->m_isSpecialWorkspace || (ws->m_monitor != g_pCompositor->m_lastMonitor && !onAllMonitors))
continue;

Expand Down
22 changes: 10 additions & 12 deletions src/helpers/Monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,12 @@ void CMonitor::onConnect(bool noRule) {

setupDefaultWS(monitorRule);

for (auto const& ws : g_pCompositor->m_workspaces) {
if (!valid(ws))
for (auto const& ws : g_pCompositor->getWorkspaces()) {
if (!valid(ws.lock()))
continue;

if (ws->m_lastMonitor == m_name || g_pCompositor->m_monitors.size() == 1 /* avoid lost workspaces on recover */) {
g_pCompositor->moveWorkspaceToMonitor(ws, m_self.lock());
g_pCompositor->moveWorkspaceToMonitor(ws.lock(), m_self.lock());
ws->startAnim(true, true, true);
ws->m_lastMonitor = "";
}
Expand Down Expand Up @@ -365,9 +365,9 @@ void CMonitor::onDisconnect(bool destroy) {

// move workspaces
std::vector<PHLWORKSPACE> wspToMove;
for (auto const& w : g_pCompositor->m_workspaces) {
for (auto const& w : g_pCompositor->getWorkspaces()) {
if (w->m_monitor == m_self || !w->m_monitor)
wspToMove.push_back(w);
wspToMove.emplace_back(w.lock());
}

for (auto const& w : wspToMove) {
Expand Down Expand Up @@ -994,7 +994,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
}

if (wsID == WORKSPACE_INVALID || (wsID >= SPECIAL_WORKSPACE_START && wsID <= -2)) {
wsID = g_pCompositor->m_workspaces.size() + 1;
wsID = std::ranges::distance(g_pCompositor->getWorkspaces()) + 1;
newDefaultWorkspaceName = std::to_string(wsID);

Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"{}\" is invalid.", g_pConfigManager->getDefaultWorkspaceFor(m_name));
Expand All @@ -1014,7 +1014,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
if (newDefaultWorkspaceName.empty())
newDefaultWorkspaceName = std::to_string(wsID);

PNEWWORKSPACE = g_pCompositor->m_workspaces.emplace_back(CWorkspace::create(wsID, m_self.lock(), newDefaultWorkspaceName));
PNEWWORKSPACE = CWorkspace::create(wsID, m_self.lock(), newDefaultWorkspaceName);
}

m_activeWorkspace = PNEWWORKSPACE;
Expand Down Expand Up @@ -1089,9 +1089,9 @@ void CMonitor::setMirror(const std::string& mirrorOf) {

// move all the WS
std::vector<PHLWORKSPACE> wspToMove;
for (auto const& w : g_pCompositor->m_workspaces) {
for (auto const& w : g_pCompositor->getWorkspaces()) {
if (w->m_monitor == m_self || !w->m_monitor)
wspToMove.push_back(w);
wspToMove.emplace_back(w.lock());
}

for (auto const& w : wspToMove) {
Expand All @@ -1114,8 +1114,6 @@ void CMonitor::setMirror(const std::string& mirrorOf) {

g_pCompositor->setActiveMonitor(g_pCompositor->m_monitors.front());

g_pCompositor->sanityCheckWorkspaces();

// Software lock mirrored monitor
g_pPointerManager->lockSoftwareForMonitor(PMIRRORMON);
}
Expand Down Expand Up @@ -1150,7 +1148,7 @@ static bool shouldWraparound(const WORKSPACEID id1, const WORKSPACEID id2) {
WORKSPACEID lowestID = INT64_MAX;
WORKSPACEID highestID = INT64_MIN;

for (auto const& w : g_pCompositor->m_workspaces) {
for (auto const& w : g_pCompositor->getWorkspaces()) {
if (w->m_id < 0 || w->m_isSpecialWorkspace)
continue;
lowestID = std::min(w->m_id, lowestID);
Expand Down
2 changes: 1 addition & 1 deletion src/managers/input/Swipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void CInputManager::onSwipeBegin(IPointer::SSwipeBeginEvent e) {
return;

int onMonitor = 0;
for (auto const& w : g_pCompositor->m_workspaces) {
for (auto const& w : g_pCompositor->getWorkspaces()) {
if (w->m_monitor == g_pCompositor->m_lastMonitor && !g_pCompositor->isWorkspaceSpecial(w->m_id))
onMonitor++;
}
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/ExtWorkspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ void CExtWorkspaceManagerResource::init(WP<CExtWorkspaceManagerResource> self) {
onMonitorCreated(m);
}

for (auto const& w : g_pCompositor->m_workspaces) {
onWorkspaceCreated(w);
for (auto const& w : g_pCompositor->getWorkspaces()) {
onWorkspaceCreated(w.lock());
}
}

Expand Down
Loading
Loading