commit d5b624e931bbbe4c30fa61eb2deb3ba5809aa80b
parent f083ef490d046f3cbb6c000f1f6e2a25743fed22
Author: deurzen <m.deurzen@tum.de>
Date: Sat, 4 Sep 2021 11:19:08 +0200
implements default rules config handling
Diffstat:
4 files changed, 145 insertions(+), 15 deletions(-)
diff --git a/src/core/config.cc b/src/core/config.cc
@@ -87,6 +87,82 @@ Config::Config()
}
}
}
+
+ { // produce vector of default spawn rules
+ std::ifstream in(directory + std::string("defaultrules"));
+
+ if (in.good()) {
+ std::string line;
+
+ while (std::getline(in, line)) {
+ std::string::size_type pos = line.find('#');
+
+ if (pos != std::string::npos)
+ line = line.substr(0, pos);
+
+ if (line.length() < 5)
+ continue;
+
+ line.erase(4, line.find_first_not_of(" \t\n\r\f\v"));
+ line.erase(line.find_last_not_of(" \t\n\r\f\v") + 1);
+
+ if (line.length() < 5)
+ continue;
+
+ pos = line.find(':');
+ std::string rules = line.substr(0, pos);
+
+ if (pos == std::string::npos || rules.empty() || pos >= (line.size() - 1))
+ continue;
+
+ line = line.substr(pos + 1);
+
+ if (line.length() < 5)
+ continue;
+
+ SearchSelector::SelectionCriterium criterium;
+
+ switch (line[1]) {
+ case 'N':
+ {
+ switch (line[0]) {
+ case '=': criterium = SearchSelector::SelectionCriterium::ByNameEquals; break;
+ case '~': criterium = SearchSelector::SelectionCriterium::ByNameContains; break;
+ default: continue;
+ }
+
+ break;
+ }
+ case 'C':
+ {
+ switch (line[0]) {
+ case '=': criterium = SearchSelector::SelectionCriterium::ByClassEquals; break;
+ case '~': criterium = SearchSelector::SelectionCriterium::ByClassContains; break;
+ default: continue;
+ }
+
+ break;
+ }
+ case 'I':
+ {
+ switch (line[0]) {
+ case '=': criterium = SearchSelector::SelectionCriterium::ByInstanceEquals; break;
+ case '~': criterium = SearchSelector::SelectionCriterium::ByInstanceContains; break;
+ default: continue;
+ }
+
+ break;
+ }
+ default: continue;
+ }
+
+ default_rules.push_back({
+ new SearchSelector{criterium, line.substr(3)},
+ Rules::parse_rules(rules, true)
+ });
+ }
+ }
+ }
}
Config::~Config()
diff --git a/src/core/config.hh b/src/core/config.hh
@@ -2,6 +2,7 @@
#define __CONFIG_H_GUARD__
#include "search.hh"
+#include "rules.hh"
#include <string>
#include <vector>
@@ -35,6 +36,8 @@ struct Config
std::vector<SearchSelector_ptr> ignored_producers;
std::vector<SearchSelector_ptr> ignored_consumers;
+ std::vector<std::tuple<SearchSelector_ptr, Rules>> default_rules;
+
};
#endif//__CONFIG_H_GUARD__
diff --git a/src/core/model.cc b/src/core/model.cc
@@ -428,7 +428,7 @@ Model::Model(Connection& conn)
CALL(activate_next_workspace(Direction::Backward))
},
{ { Key::One, { Main } },
- CALL(activate_workspace(Util::Change<Index> { 0 }))
+ CALL(activate_workspace(Util::Change<Index>{ 0 }))
},
{ { Key::Two, { Main } },
CALL(activate_workspace(1))
@@ -1516,6 +1516,8 @@ Model::render_decoration(Client_ptr client)
void
Model::manage(const Window window, const bool ignore, const bool may_map)
{
+ static std::unordered_map<std::string, Rules> default_rules_memoized = {};
+
std::optional<Region> window_geometry = m_conn.get_window_geometry(window);
if (ignore || !window_geometry) {
@@ -1547,6 +1549,10 @@ Model::manage(const Window window, const bool ignore, const bool may_map)
std::string class_ = m_conn.get_icccm_window_class(window);
std::string instance = m_conn.get_icccm_window_instance(window);
+ std::string client_handle = name
+ + ":" + class_
+ + ":" + instance;
+
std::unordered_set<WindowType> types = m_conn.get_window_types(window);
std::unordered_set<WindowState> states = m_conn.get_window_states(window);
@@ -1625,7 +1631,19 @@ Model::manage(const Window window, const bool ignore, const bool may_map)
client->leader = leader;
}
- Rules rules = Rules::parse_rules(client);
+ std::optional<Rules> default_rules
+ = Util::retrieve(default_rules_memoized, client_handle);
+
+ if (!default_rules)
+ for (auto& [selector,default_rules_] : m_config.default_rules)
+ if (client_matches_search(client, *selector)) {
+ default_rules_memoized[client_handle] = default_rules_;
+ default_rules = default_rules_;
+ }
+
+ Rules rules = default_rules
+ ? Rules::merge_rules(*default_rules, Rules::parse_rules(client->instance))
+ : Rules::parse_rules(client->instance);
if (center || (rules.do_center && *rules.do_center)) {
const Region screen_region = active_screen().placeable_region();
diff --git a/src/core/rules.hh b/src/core/rules.hh
@@ -7,6 +7,7 @@
#include <optional>
#include <vector>
+#include <iostream>
struct Rules
{
@@ -33,31 +34,31 @@ struct Rules
std::optional<std::vector<winsys::Edge>> snap_edges;
static Rules
- parse_rules(Client_ptr client)
+ parse_rules(std::string_view rule, bool ignore_prefix = false)
{
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;
+ 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())
+ if (!ignore_prefix && rule.size() <= prefix.size())
return rules;
auto res = std::mismatch(
- prefix.begin(),
- prefix.end(),
- client->instance.begin()
- );
+ prefix.begin(),
+ prefix.end(),
+ rule.begin()
+ );
- if (res.first == prefix.end()) {
+ if (ignore_prefix || res.first == prefix.end()) {
bool invert = false;
bool next_partition = false;
bool next_context = false;
@@ -65,7 +66,7 @@ struct Rules
std::optional<decltype(snapedge_list_handler)> list_handler = std::nullopt;
- for (auto iter = res.second; iter != client->instance.end(); ++iter) {
+ for (auto iter = res.second; iter != rule.end(); ++iter) {
if (*iter == '.') {
list_handler = std::nullopt;
continue;
@@ -135,6 +136,38 @@ struct Rules
return rules;
}
+
+ static Rules
+ merge_rules(Rules const& base, Rules const& merger)
+ {
+ Rules rules = base;
+
+ if (merger.do_focus)
+ rules.do_focus = merger.do_focus;
+
+ if (merger.do_float)
+ rules.do_float = merger.do_float;
+
+ if (merger.do_center)
+ rules.do_center = merger.do_center;
+
+ if (merger.do_fullscreen)
+ rules.do_fullscreen = merger.do_fullscreen;
+
+ if (merger.to_partition)
+ rules.to_partition = merger.to_partition;
+
+ if (merger.to_context)
+ rules.to_context = merger.to_context;
+
+ if (merger.to_workspace)
+ rules.to_workspace = merger.to_workspace;
+
+ if (merger.snap_edges)
+ rules.snap_edges = merger.snap_edges;
+
+ return rules;
+ }
};
#endif//__RULES_H_GUARD__