kranewm

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in C++
git clone git clone git://git.deurzen.net/kranewm.git
Log | Files | Refs | LICENSE

commit 37695b23b396c523337ff4897379e96bb2940602
parent b614c5ffff2b35530444446c9ec20b7b821202f5
Author: deurzen <m.deurzen@tum.de>
Date:   Tue, 21 Sep 2021 23:15:41 +0200

adds initial partition (screen) syncing functionality

Diffstat:
Msrc/core/cycle.hh | 28++++++++++++++++++++++++++++
Msrc/core/model.cc | 53+++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/core/partition.hh | 21++++++++++++++++++++-
Msrc/winsys/geometry.hh | 6+++---
Msrc/winsys/util.cc | 9+++++++++
Msrc/winsys/util.hh | 1+
6 files changed, 108 insertions(+), 10 deletions(-)

diff --git a/src/core/cycle.hh b/src/core/cycle.hh @@ -81,11 +81,39 @@ public: void activate_at_index(Index); void activate_element(T); + template<typename UnaryPredicate> + void activate_for_condition(UnaryPredicate predicate) + { + auto it = std::find_if( + m_elements.begin(), + m_elements.end(), + predicate + ); + + if (it != m_elements.end()) + activate_element(*it); + } + bool remove_first(); bool remove_last(); bool remove_at_index(Index); bool remove_element(T); + template<typename UnaryPredicate> + bool remove_for_condition(UnaryPredicate predicate) + { + auto it = std::find_if( + m_elements.begin(), + m_elements.end(), + predicate + ); + + if (it != m_elements.end()) + return remove_element(*it); + + return false; + } + std::optional<T> pop_back(); void replace_element(T, T); diff --git a/src/core/model.cc b/src/core/model.cc @@ -848,23 +848,64 @@ void Model::acquire_partitions() { std::size_t index = m_partitions.active_index(); + std::vector<Screen> connected_outputs = m_conn.connected_outputs(); - for (std::size_t i = 0; i < m_partitions.size(); ++i) + connected_outputs.erase( + std::unique( + connected_outputs.begin(), + connected_outputs.end(), + [](Screen const& screen1, Screen const& screen2) { + return screen1.full_region() == screen2.full_region(); + } + ), + connected_outputs.end() + ); + + if (connected_outputs.size() > m_contexts.size()) { + // TODO: generate more contexts? + spdlog::warn("more outputs than available contexts"); + return; + } + + if (connected_outputs.empty()) { + spdlog::warn("could not acquire any partitions"); + return; + } + + std::vector<Context_ptr> partition_contexts( + std::max(connected_outputs.size(), m_partitions.size()), + nullptr + ); + + std::unordered_set<Index> used_contexts{}; + + for (std::size_t i = 0; i < m_partitions.size(); ++i) { + partition_contexts[m_partitions[i]->index()] = m_partitions[i]->context(); + used_contexts.insert(m_partitions[i]->context()->index()); delete m_partitions[i]; + } m_partitions.clear(); - std::vector<Screen> connected_outputs = m_conn.connected_outputs(); + std::vector<Partition_ptr> contextless_partitions{}; - for (std::size_t i = 0; i < connected_outputs.size(); ++i) + for (std::size_t i = 0; i < connected_outputs.size(); ++i) { m_partitions.insert_at_back(new Partition( connected_outputs[i], i )); - if (m_partitions.empty()) { - spdlog::warn("could not acquire any partitions"); - return; + if (partition_contexts[i] != nullptr) + m_partitions[i]->set_context(partition_contexts[i]); + else + contextless_partitions.push_back(m_partitions[i]); + } + + for (std::size_t i = 0, context_index = 0; i < contextless_partitions.size(); ++context_index) { + if (Util::contains(used_contexts, context_index)) + continue; + + contextless_partitions[i++]->set_context(m_contexts[context_index]); } if (index < m_partitions.size()) diff --git a/src/core/partition.hh b/src/core/partition.hh @@ -3,13 +3,15 @@ #include "../winsys/common.hh" #include "../winsys/screen.hh" +#include "context.hh" typedef class Partition final { public: Partition(winsys::Screen screen, Index index) : m_screen(screen), - m_index(index) + m_index(index), + mp_context(nullptr) {} winsys::Screen& @@ -30,10 +32,27 @@ public: return m_index; } + void + set_context(Context_ptr context) + { + Util::assert(context != nullptr, + "partition must contain valid context"); + + mp_context = context; + } + + Context_ptr + context() + { + return mp_context; + } + private: winsys::Screen m_screen; Index m_index; + Context_ptr mp_context; + }* Partition_ptr; #endif//__PARTITION_H_GUARD__ diff --git a/src/winsys/geometry.hh b/src/winsys/geometry.hh @@ -36,7 +36,7 @@ namespace winsys }; inline bool - operator==(Dim& lhs, Dim& rhs) + operator==(Dim const& lhs, Dim const& rhs) { return lhs.w == rhs.w && lhs.h == rhs.h; } @@ -63,7 +63,7 @@ namespace winsys }; inline bool - operator==(Pos& lhs, Pos& rhs) + operator==(Pos const& lhs, Pos const& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } @@ -89,7 +89,7 @@ namespace winsys }; inline bool - operator==(Region& lhs, Region& rhs) + operator==(Region const& lhs, Region const& rhs) { return lhs.pos == rhs.pos && lhs.dim == rhs.dim; } diff --git a/src/winsys/util.cc b/src/winsys/util.cc @@ -1,5 +1,7 @@ #include "util.hh" +#include <utility> + extern "C" { #include <unistd.h> } @@ -16,3 +18,10 @@ Util::warn(const std::string&& msg) { std::cerr << msg << std::endl; } + +void +Util::assert(bool condition, const std::string&& msg) +{ + if (!condition) + Util::die(std::forward<const std::string&&>(msg)); +} diff --git a/src/winsys/util.hh b/src/winsys/util.hh @@ -13,6 +13,7 @@ namespace Util void die(const std::string&&); void warn(const std::string&&); + void assert(bool, const std::string&&); template < typename T,