kranewm

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

rules.hh (4811B)


      1 #ifndef __RULES_H_GUARD__
      2 #define __RULES_H_GUARD__
      3 
      4 #include "../winsys/geometry.hh"
      5 #include "client.hh"
      6 #include "defaults.hh"
      7 
      8 #include <optional>
      9 #include <vector>
     10 #include <iostream>
     11 
     12 struct Rules
     13 {
     14     Rules()
     15         : do_focus(std::nullopt),
     16           do_float(std::nullopt),
     17           do_center(std::nullopt),
     18           do_fullscreen(std::nullopt),
     19           to_partition(std::nullopt),
     20           to_context(std::nullopt),
     21           to_workspace(std::nullopt),
     22           snap_edges(std::nullopt)
     23     {}
     24 
     25     ~Rules() = default;
     26 
     27     std::optional<bool> do_focus;
     28     std::optional<bool> do_float;
     29     std::optional<bool> do_center;
     30     std::optional<bool> do_fullscreen;
     31     std::optional<Index> to_partition;
     32     std::optional<Index> to_context;
     33     std::optional<Index> to_workspace;
     34     std::optional<std::vector<winsys::Edge>> snap_edges;
     35 
     36     static Rules
     37     parse_rules(std::string_view rule, bool ignore_prefix = false)
     38     {
     39         static std::string prefix = WM_NAME + ":";
     40         static auto snapedge_list_handler = [](Rules& rules, auto iter) {
     41             switch (*iter) {
     42             case 'l': rules.snap_edges->push_back(winsys::Edge::Left);   return;
     43             case 't': rules.snap_edges->push_back(winsys::Edge::Top);    return;
     44             case 'r': rules.snap_edges->push_back(winsys::Edge::Right);  return;
     45             case 'b': rules.snap_edges->push_back(winsys::Edge::Bottom); return;
     46             default: return;
     47             }
     48         };
     49 
     50         Rules rules{};
     51 
     52         if (!ignore_prefix && rule.size() <= prefix.size())
     53             return rules;
     54 
     55         auto res = std::mismatch(
     56             prefix.begin(),
     57             prefix.end(),
     58             rule.begin()
     59         );
     60 
     61         if (ignore_prefix || res.first == prefix.end()) {
     62             bool invert = false;
     63             bool next_partition = false;
     64             bool next_context = false;
     65             bool next_workspace = false;
     66 
     67             std::optional<decltype(snapedge_list_handler)> list_handler = std::nullopt;
     68 
     69             for (auto iter = res.second; iter != rule.end(); ++iter) {
     70                 if (*iter == '.') {
     71                     list_handler = std::nullopt;
     72                     continue;
     73                 }
     74 
     75                 if (list_handler) {
     76                     (*list_handler)(rules, iter);
     77                     continue;
     78                 }
     79 
     80                 if (*iter == '!') {
     81                     invert = true;
     82                     continue;
     83                 }
     84 
     85                 if (*iter == 'P') {
     86                     next_partition = true;
     87                     continue;
     88                 }
     89 
     90                 if (*iter == 'C') {
     91                     next_context = true;
     92                     continue;
     93                 }
     94 
     95                 if (*iter == 'W') {
     96                     next_workspace = true;
     97                     continue;
     98                 }
     99 
    100                 if (*iter == '@')
    101                     rules.do_focus = !invert;
    102 
    103                 if (*iter == 'f')
    104                     rules.do_float = !invert;
    105 
    106                 if (*iter == 'F')
    107                     rules.do_fullscreen = !invert;
    108 
    109                 if (*iter == 'c')
    110                     rules.do_center = !invert;
    111 
    112                 if (*iter >= '0' && *iter <= '9') {
    113                     if (next_partition)
    114                         rules.to_partition = *iter - '0';
    115 
    116                     if (next_context)
    117                         rules.to_context = *iter - '0';
    118 
    119                     if (next_workspace)
    120                         rules.to_workspace = *iter - '0';
    121                 }
    122 
    123                 if (*iter == 'S') {
    124                     if (!rules.snap_edges)
    125                         rules.snap_edges = std::vector<winsys::Edge>{};
    126 
    127                     list_handler = snapedge_list_handler;
    128                 }
    129 
    130                 invert = false;
    131                 next_partition = false;
    132                 next_context = false;
    133                 next_workspace = false;
    134             }
    135         }
    136 
    137         return rules;
    138     }
    139 
    140     static Rules
    141     merge_rules(Rules const& base, Rules const& merger)
    142     {
    143         Rules rules = base;
    144 
    145         if (merger.do_focus)
    146             rules.do_focus = merger.do_focus;
    147 
    148         if (merger.do_float)
    149             rules.do_float = merger.do_float;
    150 
    151         if (merger.do_center)
    152             rules.do_center = merger.do_center;
    153 
    154         if (merger.do_fullscreen)
    155             rules.do_fullscreen = merger.do_fullscreen;
    156 
    157         if (merger.to_partition)
    158             rules.to_partition = merger.to_partition;
    159 
    160         if (merger.to_context)
    161             rules.to_context = merger.to_context;
    162 
    163         if (merger.to_workspace)
    164             rules.to_workspace = merger.to_workspace;
    165 
    166         if (merger.snap_edges)
    167             rules.snap_edges = merger.snap_edges;
    168 
    169         return rules;
    170     }
    171 };
    172 
    173 #endif//__RULES_H_GUARD__