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 8a8d0aa9dac091d7788c44abcdbd7c7e5ec7ff72
parent a6ad28e33ecf37f90e651bf153e946c2eb405086
Author: deurzen <m.deurzen@tum.de>
Date:   Sat,  4 Sep 2021 08:02:46 +0200

adds list-type spawn rule support, snap edge rule

Diffstat:
Msrc/core/model.cc | 82+++++--------------------------------------------------------------------------
Msrc/core/rules.hh | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 115 insertions(+), 79 deletions(-)

diff --git a/src/core/model.cc b/src/core/model.cc @@ -1608,82 +1608,6 @@ Model::render_decoration(Client_ptr client) } -Rules -Model::retrieve_rules(Client_ptr client) const -{ - static std::string prefix = WM_NAME + ":"; - Rules rules = {}; - - if (client->instance.size() <= prefix.size()) - return rules; - - auto res = std::mismatch( - prefix.begin(), - prefix.end(), - client->instance.begin() - ); - - if (res.first == prefix.end()) { - bool invert = false; - bool next_partition = false; - bool next_context = false; - bool next_workspace = false; - - for (auto iter = res.second; iter != client->instance.end(); ++iter) { - if (*iter == '!') { - invert = true; - continue; - } - - if (*iter == 'P') { - next_partition = true; - continue; - } - - if (*iter == 'C') { - next_context = true; - continue; - } - - if (*iter == 'W') { - next_workspace = true; - continue; - } - - if (*iter == '@') - rules.do_focus = !invert; - - if (*iter == 'f') - rules.do_float = !invert; - - if (*iter == 'F') - rules.do_fullscreen = !invert; - - if (*iter == 'c') - rules.do_center = !invert; - - if (*iter >= '0' && *iter <= '9') { - if (next_partition) - rules.to_partition = *iter - '0'; - - if (next_context) - rules.to_context = *iter - '0'; - - if (next_workspace) - rules.to_workspace = *iter - '0'; - } - - invert = false; - next_partition = false; - next_context = false; - next_workspace = false; - } - } - - return rules; -} - - void Model::manage(const Window window, const bool ignore, const bool may_map) { @@ -1796,7 +1720,7 @@ Model::manage(const Window window, const bool ignore, const bool may_map) client->leader = leader; } - Rules rules = retrieve_rules(client); + Rules rules = Rules::parse_rules(client); if (center || (rules.do_center && *rules.do_center)) { const Region screen_region = active_screen().placeable_region(); @@ -1885,6 +1809,10 @@ Model::manage(const Window window, const bool ignore, const bool may_map) get_workspace(client->workspace)->add_client(client); + if (rules.snap_edges) + for(auto& edge : *rules.snap_edges) + snap_client(edge, client); + if (client->workspace == mp_workspace->index()) { apply_layout(mp_workspace); diff --git a/src/core/rules.hh b/src/core/rules.hh @@ -1,9 +1,12 @@ #ifndef __RULES_H_GUARD__ #define __RULES_H_GUARD__ -#include "../winsys/common.hh" +#include "../winsys/geometry.hh" +#include "client.hh" +#include "defaults.hh" #include <optional> +#include <vector> struct Rules { @@ -14,7 +17,8 @@ struct Rules do_fullscreen(std::nullopt), to_partition(std::nullopt), to_context(std::nullopt), - to_workspace(std::nullopt) + to_workspace(std::nullopt), + snap_edges(std::nullopt) {} ~Rules() = default; @@ -26,7 +30,111 @@ struct Rules std::optional<Index> to_partition; std::optional<Index> to_context; std::optional<Index> to_workspace; + std::optional<std::vector<winsys::Edge>> snap_edges; + static Rules + parse_rules(Client_ptr client) + { + static std::string prefix = WM_NAME + ":"; + static auto snapedge_list_handler = [](Rules& rules, auto iter) { + switch (*iter) { + case 'l': rules.snap_edges->push_back(winsys::Edge::Left); return; + case 't': rules.snap_edges->push_back(winsys::Edge::Top); return; + case 'r': rules.snap_edges->push_back(winsys::Edge::Right); return; + case 'b': rules.snap_edges->push_back(winsys::Edge::Bottom); return; + default: return; + } + }; + + Rules rules = {}; + + if (client->instance.size() <= prefix.size()) + return rules; + + auto res = std::mismatch( + prefix.begin(), + prefix.end(), + client->instance.begin() + ); + + if (res.first == prefix.end()) { + bool invert = false; + bool next_partition = false; + bool next_context = false; + bool next_workspace = false; + + std::optional<decltype(snapedge_list_handler)> list_handler = std::nullopt; + + for (auto iter = res.second; iter != client->instance.end(); ++iter) { + if (*iter == '.') { + list_handler = std::nullopt; + continue; + } + + if (list_handler) { + (*list_handler)(rules, iter); + continue; + } + + if (*iter == '!') { + invert = true; + continue; + } + + if (*iter == 'P') { + next_partition = true; + continue; + } + + if (*iter == 'C') { + next_context = true; + continue; + } + + if (*iter == 'W') { + next_workspace = true; + continue; + } + + if (*iter == '@') + rules.do_focus = !invert; + + if (*iter == 'f') + rules.do_float = !invert; + + if (*iter == 'F') + rules.do_fullscreen = !invert; + + if (*iter == 'c') + rules.do_center = !invert; + + if (*iter >= '0' && *iter <= '9') { + if (next_partition) + rules.to_partition = *iter - '0'; + + if (next_context) + rules.to_context = *iter - '0'; + + if (next_workspace) + rules.to_workspace = *iter - '0'; + } + + if (*iter == 'S') { + if (!rules.snap_edges) + rules.snap_edges = std::vector<winsys::Edge>{}; + + list_handler = snapedge_list_handler; + } + + invert = false; + next_partition = false; + next_context = false; + next_workspace = false; + } + } + + return rules; + } }; #endif//__RULES_H_GUARD__