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:
M | src/core/model.cc | | | 82 | +++++-------------------------------------------------------------------------- |
M | src/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__