#include "WorkspaceAlgoMatcher.hpp" #include "../../config/ConfigValue.hpp" #include "../../config/shared/workspace/WorkspaceRuleManager.hpp" #include "../algorithm/Algorithm.hpp" #include "../algorithm/TiledAlgorithm.hpp" #include "../space/Space.hpp" #include "../algorithm/floating/default/DefaultFloatingAlgorithm.hpp" #include "../algorithm/tiled/dwindle/DwindleAlgorithm.hpp" #include "../algorithm/tiled/master/MasterAlgorithm.hpp" #include "../algorithm/tiled/scrolling/ScrollingAlgorithm.hpp" #include "../algorithm/tiled/monocle/MonocleAlgorithm.hpp" #include "../../Compositor.hpp" using namespace Layout; using namespace Layout::Supplementary; constexpr const char* DEFAULT_FLOATING_ALGO = "default"; constexpr const char* DEFAULT_TILED_ALGO = "dwindle"; const UP& Supplementary::algoMatcher() { static UP m = makeUnique(); return m; } CWorkspaceAlgoMatcher::CWorkspaceAlgoMatcher() { m_tiledAlgos = { {"dwindle", [] { return makeUnique(); }}, {"master", [] { return makeUnique(); }}, {"scrolling", [] { return makeUnique(); }}, {"monocle", [] { return makeUnique(); }}, }; m_floatingAlgos = { {"default", [] { return makeUnique(); }}, }; m_algoNames = { {&typeid(Tiled::CDwindleAlgorithm), "dwindle"}, {&typeid(Tiled::CMasterAlgorithm), "master"}, {&typeid(Tiled::CScrollingAlgorithm), "scrolling"}, {&typeid(Tiled::CMonocleAlgorithm), "monocle"}, {&typeid(Floating::CDefaultFloatingAlgorithm), "default"}, }; } bool CWorkspaceAlgoMatcher::registerTiledAlgo(const std::string& name, const std::type_info* typeInfo, std::function()>&& factory) { if (m_tiledAlgos.contains(name) || m_floatingAlgos.contains(name)) return false; m_tiledAlgos.emplace(name, std::move(factory)); m_algoNames.emplace(typeInfo, name); updateWorkspaceLayouts(); return true; } bool CWorkspaceAlgoMatcher::registerFloatingAlgo(const std::string& name, const std::type_info* typeInfo, std::function()>&& factory) { if (m_tiledAlgos.contains(name) || m_floatingAlgos.contains(name)) return false; m_floatingAlgos.emplace(name, std::move(factory)); m_algoNames.emplace(typeInfo, name); updateWorkspaceLayouts(); return true; } bool CWorkspaceAlgoMatcher::unregisterAlgo(const std::string& name) { if (!m_tiledAlgos.contains(name) && !m_floatingAlgos.contains(name)) return false; std::erase_if(m_algoNames, [&name](const auto& e) { return e.second == name; }); if (m_floatingAlgos.contains(name)) m_floatingAlgos.erase(name); else m_tiledAlgos.erase(name); // this is needed here to avoid situations where a plugin unloads and we still have a UP // to a plugin layout updateWorkspaceLayouts(); return true; } UP CWorkspaceAlgoMatcher::algoForNameTiled(const std::string& s) { if (m_tiledAlgos.contains(s)) return m_tiledAlgos.at(s)(); return m_tiledAlgos.at(DEFAULT_TILED_ALGO)(); } UP CWorkspaceAlgoMatcher::algoForNameFloat(const std::string& s) { if (m_floatingAlgos.contains(s)) return m_floatingAlgos.at(s)(); return m_floatingAlgos.at(DEFAULT_FLOATING_ALGO)(); } std::string CWorkspaceAlgoMatcher::tiledAlgoForWorkspace(const PHLWORKSPACE& w) { static auto PLAYOUT = CConfigValue("general:layout"); auto rule = Config::workspaceRuleMgr()->getWorkspaceRuleFor(w); return rule && rule->m_layout.has_value() ? rule->m_layout.value() : *PLAYOUT; } SP CWorkspaceAlgoMatcher::createAlgorithmForWorkspace(PHLWORKSPACE w) { return CAlgorithm::create(algoForNameTiled(tiledAlgoForWorkspace(w)), makeUnique(), w->m_space); } void CWorkspaceAlgoMatcher::updateWorkspaceLayouts() { // TODO: make this ID-based, string comparison is slow for (const auto& ws : g_pCompositor->getWorkspaces()) { if (!ws) continue; const auto& TILED_ALGO = ws->m_space->algorithm()->tiledAlgo(); if (!TILED_ALGO) continue; const auto LAYOUT_TO_USE = tiledAlgoForWorkspace(ws.lock()); const auto CURRENT_LAYOUT = getNameForTiledAlgo(TILED_ALGO.get()); if (CURRENT_LAYOUT == LAYOUT_TO_USE && m_tiledAlgos.contains(LAYOUT_TO_USE)) continue; // needs a switchup ws->m_space->algorithm()->updateTiledAlgo(algoForNameTiled(LAYOUT_TO_USE)); } } std::string CWorkspaceAlgoMatcher::getNameForTiledAlgo(const ITiledAlgorithm* algo) { if (!algo) return "unknown"; if (const auto name = algo->layoutName(); name.has_value()) return *name; return getNameForTiledAlgo(&typeid(*algo)); } std::string CWorkspaceAlgoMatcher::getNameForTiledAlgo(const std::type_info* type) { if (m_algoNames.contains(type)) return m_algoNames.at(type); return "unknown"; }