refactor(bspwm): Cleanup states

This commit is contained in:
Michael Carlberg 2016-11-30 21:03:28 +01:00
parent 466e9e212f
commit 6db66896bd
5 changed files with 143 additions and 133 deletions

View File

@ -33,7 +33,6 @@ class config {
string build_path(const string& section, const string& key) const; string build_path(const string& section, const string& key) const;
void warn_deprecated(const string& section, const string& key, string replacement) const; void warn_deprecated(const string& section, const string& key, string replacement) const;
/** /**
* Returns true if a given parameter exists * Returns true if a given parameter exists
*/ */

View File

@ -70,13 +70,9 @@ namespace drawtypes {
}; };
label_t load_label(const config& conf, const string& section, string name, bool required = true, string def = ""); label_t load_label(const config& conf, const string& section, string name, bool required = true, string def = "");
label_t load_optional_label(const config& conf, string section, string name, string def = ""); label_t load_optional_label(const config& conf, string section, string name, string def = "");
label_t load_either_config_label(const config& conf, string section, string name1, string name2, string def = "");
icon_t load_icon(const config& conf, string section, string name, bool required = true, string def = ""); icon_t load_icon(const config& conf, string section, string name, bool required = true, string def = "");
icon_t load_optional_icon(const config& conf, string section, string name, string def = ""); icon_t load_optional_icon(const config& conf, string section, string name, string def = "");
} }

View File

@ -6,42 +6,36 @@
POLYBAR_NS POLYBAR_NS
namespace modules { namespace modules {
enum class state_ws {
WORKSPACE_NONE,
WORKSPACE_ACTIVE,
WORKSPACE_URGENT,
WORKSPACE_EMPTY,
WORKSPACE_OCCUPIED,
WORKSPACE_FOCUSED_URGENT,
WORKSPACE_FOCUSED_EMPTY,
WORKSPACE_FOCUSED_OCCUPIED,
WORKSPACE_DIMMED, // used when the monitor is out of focus
WORKSPACE_DIMMED_ACTIVE,
WORKSPACE_DIMMED_URGENT,
WORKSPACE_DIMMED_EMPTY,
WORKSPACE_DIMMED_OCCUPIED
};
enum class state_mode {
MODE_NONE,
MODE_LAYOUT_MONOCLE,
MODE_LAYOUT_TILED,
MODE_STATE_FULLSCREEN,
MODE_STATE_FLOATING,
MODE_NODE_LOCKED,
MODE_NODE_STICKY,
MODE_NODE_PRIVATE
};
struct bspwm_monitor {
vector<pair<state_ws, label_t>> workspaces;
vector<label_t> modes;
label_t label;
string name;
bool focused = false;
};
class bspwm_module : public event_module<bspwm_module> { class bspwm_module : public event_module<bspwm_module> {
public: public:
enum class state {
NONE = 0U,
EMPTY,
OCCUPIED,
FOCUSED,
URGENT,
DIMMED, // used when the monitor is out of focus
};
enum class mode {
NONE = 0U,
LAYOUT_MONOCLE,
LAYOUT_TILED,
STATE_FULLSCREEN,
STATE_FLOATING,
NODE_LOCKED,
NODE_STICKY,
NODE_PRIVATE
};
struct bspwm_monitor {
vector<pair<uint32_t, label_t>> workspaces;
vector<label_t> modes;
label_t label;
string name;
bool focused = false;
};
using event_module::event_module; using event_module::event_module;
void setup(); void setup();
@ -56,12 +50,14 @@ namespace modules {
} }
private: private:
static constexpr auto DEFAULT_WS_ICON = "ws-icon-default"; static constexpr auto DEFAULT_ICON = "ws-icon-default";
static constexpr auto DEFAULT_WS_LABEL = "%icon% %name%"; static constexpr auto DEFAULT_LABEL = "%icon% %name%";
static constexpr auto DEFAULT_MONITOR_LABEL = "%name%"; static constexpr auto DEFAULT_MONITOR_LABEL = "%name%";
static constexpr auto TAG_LABEL_MONITOR = "<label-monitor>"; static constexpr auto TAG_LABEL_MONITOR = "<label-monitor>";
static constexpr auto TAG_LABEL_STATE = "<label-state>"; static constexpr auto TAG_LABEL_STATE = "<label-state>";
static constexpr auto TAG_LABEL_MODE = "<label-mode>"; static constexpr auto TAG_LABEL_MODE = "<label-mode>";
static constexpr auto EVENT_PREFIX = "bwm"; static constexpr auto EVENT_PREFIX = "bwm";
static constexpr auto EVENT_CLICK = "bwmf"; static constexpr auto EVENT_CLICK = "bwmf";
static constexpr auto EVENT_SCROLL_UP = "bwmn"; static constexpr auto EVENT_SCROLL_UP = "bwmn";
@ -71,8 +67,8 @@ namespace modules {
vector<unique_ptr<bspwm_monitor>> m_monitors; vector<unique_ptr<bspwm_monitor>> m_monitors;
map<state_mode, label_t> m_modelabels; map<mode, label_t> m_modelabels;
map<state_ws, label_t> m_statelabels; map<uint32_t, label_t> m_statelabels;
label_t m_monitorlabel; label_t m_monitorlabel;
iconset_t m_icons; iconset_t m_icons;

View File

@ -167,13 +167,6 @@ namespace drawtypes {
return load_label(conf, move(section), move(name), false, move(def)); return load_label(conf, move(section), move(name), false, move(def));
} }
label_t load_either_config_label(const config& conf, string section, string name1, string name2, string def) {
if (conf.has<string>(section, name1))
return load_label(conf, section, name1, true, "");
else
return load_optional_label(conf, section, name2, def);
}
/** /**
* Create an icon by loading values from the configuration * Create an icon by loading values from the configuration
*/ */

View File

@ -10,6 +10,28 @@
POLYBAR_NS POLYBAR_NS
namespace {
using bspwm_state = modules::bspwm_module::state;
uint32_t make_mask(bspwm_state s1, bspwm_state s2 = bspwm_state::NONE) {
uint32_t mask{0U};
if (static_cast<uint32_t>(s1))
mask |= 1 << (static_cast<uint32_t>(s1) - 1);
if (static_cast<uint32_t>(s2))
mask |= 1 << (static_cast<uint32_t>(s2) - 1);
return mask;
}
// uint32_t check_mask(uint32_t base, bspwm_state s1, bspwm_state s2 = bspwm_state::NONE) {
// uint32_t mask{0U};
// if (static_cast<uint32_t>(s1))
// mask |= 1 << (static_cast<uint32_t>(s1) - 1);
// if (static_cast<uint32_t>(s2))
// mask |= 1 << (static_cast<uint32_t>(s2) - 1);
// return (base & mask) == mask;
// }
}
namespace modules { namespace modules {
template class module<bspwm_module>; template class module<bspwm_module>;
template class event_module<bspwm_module>; template class event_module<bspwm_module>;
@ -37,49 +59,65 @@ namespace modules {
} }
if (m_formatter->has(TAG_LABEL_STATE)) { if (m_formatter->has(TAG_LABEL_STATE)) {
m_statelabels.insert( // XXX: Warn about deprecated parameters
make_pair(state_ws::WORKSPACE_ACTIVE, load_optional_label(m_conf, name(), "label-active", DEFAULT_WS_LABEL))); m_conf.warn_deprecated(name(), "label-dimmed-active", "label-dimmed-focused");
m_statelabels.insert(make_pair(
state_ws::WORKSPACE_OCCUPIED, load_optional_label(m_conf, name(), "label-occupied", DEFAULT_WS_LABEL))); // clang-format off
m_statelabels.insert( try {
make_pair(state_ws::WORKSPACE_URGENT, load_optional_label(m_conf, name(), "label-urgent", DEFAULT_WS_LABEL))); m_statelabels.emplace(make_mask(state::FOCUSED), load_label(m_conf, name(), "label-active", DEFAULT_LABEL));
m_statelabels.insert( m_conf.warn_deprecated(name(), "label-active", "label-focused and label-dimmed-focused");
make_pair(state_ws::WORKSPACE_OCCUPIED, load_optional_label(m_conf, name(), "label-occupied", DEFAULT_WS_LABEL))); } catch (const key_error& err) {
m_statelabels.insert( m_statelabels.emplace(make_mask(state::FOCUSED), load_optional_label(m_conf, name(), "label-focused", DEFAULT_LABEL));
make_pair(state_ws::WORKSPACE_EMPTY, load_optional_label(m_conf, name(), "label-empty", DEFAULT_WS_LABEL))); }
m_statelabels.insert(
make_pair(state_ws::WORKSPACE_FOCUSED_OCCUPIED, load_either_config_label(m_conf, name(), "label-focused-occupied", "label-focused", DEFAULT_WS_LABEL))); m_statelabels.emplace(make_mask(state::OCCUPIED),
m_statelabels.insert( load_optional_label(m_conf, name(), "label-occupied", DEFAULT_LABEL));
make_pair(state_ws::WORKSPACE_FOCUSED_URGENT, load_either_config_label(m_conf, name(), "label-focused-urgent", "label-focused", DEFAULT_WS_LABEL))); m_statelabels.emplace(make_mask(state::URGENT),
m_statelabels.insert( load_optional_label(m_conf, name(), "label-urgent", DEFAULT_LABEL));
make_pair(state_ws::WORKSPACE_FOCUSED_EMPTY, load_either_config_label(m_conf, name(), "label-focused-empty", "label-focused", DEFAULT_WS_LABEL))); m_statelabels.emplace(make_mask(state::EMPTY),
m_statelabels.insert(make_pair(state_ws::WORKSPACE_DIMMED, load_optional_label(m_conf, name(), "label-dimmed"))); load_optional_label(m_conf, name(), "label-empty", DEFAULT_LABEL));
m_statelabels.insert( m_statelabels.emplace(make_mask(state::DIMMED),
make_pair(state_ws::WORKSPACE_DIMMED_ACTIVE, load_optional_label(m_conf, name(), "label-dimmed-active"))); load_optional_label(m_conf, name(), "label-dimmed"));
m_statelabels.insert(
make_pair(state_ws::WORKSPACE_DIMMED_URGENT, load_optional_label(m_conf, name(), "label-dimmed-urgent"))); vector<pair<state, string>> focused_overrides{
m_statelabels.insert( {state::OCCUPIED, "label-focused-occupied"},
make_pair(state_ws::WORKSPACE_DIMMED_EMPTY, load_optional_label(m_conf, name(), "label-dimmed-empty"))); {state::URGENT, "label-focused-urgent"},
m_statelabels.insert( {state::EMPTY, "label-focused-empty"}};
make_pair(state_ws::WORKSPACE_DIMMED_OCCUPIED, load_optional_label(m_conf, name(), "label-dimmed-occupied")));
for (auto&& os : focused_overrides) {
uint32_t mask{make_mask(state::FOCUSED, os.first)};
try {
m_statelabels.emplace(mask, load_label(m_conf, name(), os.second));
} catch (const key_error& err) {
m_statelabels.emplace(mask, m_statelabels.at(make_mask(state::FOCUSED))->clone());
}
}
vector<pair<state, string>> dimmed_overrides{
{state::FOCUSED, "label-dimmed-focused"},
{state::OCCUPIED, "label-dimmed-occupied"},
{state::URGENT, "label-dimmed-urgent"},
{state::EMPTY, "label-dimmed-empty"}};
for (auto&& os : dimmed_overrides) {
m_statelabels.emplace(make_mask(state::DIMMED, os.first),
load_optional_label(m_conf, name(), os.second, m_statelabels.at(make_mask(os.first))->get()));
}
// clang-format on
} }
if (m_formatter->has(TAG_LABEL_MODE)) { if (m_formatter->has(TAG_LABEL_MODE)) {
m_modelabels.insert( m_modelabels.emplace(mode::LAYOUT_MONOCLE, load_optional_label(m_conf, name(), "label-monocle"));
make_pair(state_mode::MODE_LAYOUT_MONOCLE, load_optional_label(m_conf, name(), "label-monocle"))); m_modelabels.emplace(mode::LAYOUT_TILED, load_optional_label(m_conf, name(), "label-tiled"));
m_modelabels.insert(make_pair(state_mode::MODE_LAYOUT_TILED, load_optional_label(m_conf, name(), "label-tiled"))); m_modelabels.emplace(mode::STATE_FULLSCREEN, load_optional_label(m_conf, name(), "label-fullscreen"));
m_modelabels.insert( m_modelabels.emplace(mode::STATE_FLOATING, load_optional_label(m_conf, name(), "label-floating"));
make_pair(state_mode::MODE_STATE_FULLSCREEN, load_optional_label(m_conf, name(), "label-fullscreen"))); m_modelabels.emplace(mode::NODE_LOCKED, load_optional_label(m_conf, name(), "label-locked"));
m_modelabels.insert( m_modelabels.emplace(mode::NODE_STICKY, load_optional_label(m_conf, name(), "label-sticky"));
make_pair(state_mode::MODE_STATE_FLOATING, load_optional_label(m_conf, name(), "label-floating"))); m_modelabels.emplace(mode::NODE_PRIVATE, load_optional_label(m_conf, name(), "label-private"));
m_modelabels.insert(make_pair(state_mode::MODE_NODE_LOCKED, load_optional_label(m_conf, name(), "label-locked")));
m_modelabels.insert(make_pair(state_mode::MODE_NODE_STICKY, load_optional_label(m_conf, name(), "label-sticky")));
m_modelabels.insert(
make_pair(state_mode::MODE_NODE_PRIVATE, load_optional_label(m_conf, name(), "label-private")));
} }
m_icons = make_shared<iconset>(); m_icons = make_shared<iconset>();
m_icons->add(DEFAULT_WS_ICON, make_shared<label>(m_conf.get<string>(name(), DEFAULT_WS_ICON, ""))); m_icons->add(DEFAULT_ICON, make_shared<label>(m_conf.get<string>(name(), DEFAULT_ICON, "")));
for (const auto& workspace : m_conf.get_list<string>(name(), "ws-icon", {})) { for (const auto& workspace : m_conf.get_list<string>(name(), "ws-icon", {})) {
auto vec = string_util::split(workspace, ';'); auto vec = string_util::split(workspace, ';');
@ -182,8 +220,8 @@ namespace modules {
} }
auto value = !tag.empty() ? tag.substr(1) : ""; auto value = !tag.empty() ? tag.substr(1) : "";
auto workspace_flag = state_ws::WORKSPACE_NONE; auto mode_flag = mode::NONE;
auto mode_flag = state_mode::MODE_NONE; uint32_t workspace_mask{0U};
if (tag[0] == 'm' || tag[0] == 'M') { if (tag[0] == 'm' || tag[0] == 'M') {
m_monitors.emplace_back(make_unique<bspwm_monitor>()); m_monitors.emplace_back(make_unique<bspwm_monitor>());
@ -203,32 +241,32 @@ namespace modules {
m_monitors.back()->focused = true; m_monitors.back()->focused = true;
break; break;
case 'F': case 'F':
workspace_flag = state_ws::WORKSPACE_FOCUSED_EMPTY; workspace_mask = make_mask(state::FOCUSED, state::EMPTY);
break; break;
case 'O': case 'O':
workspace_flag = state_ws::WORKSPACE_FOCUSED_OCCUPIED; workspace_mask = make_mask(state::FOCUSED, state::OCCUPIED);
break; break;
case 'U': case 'U':
workspace_flag = state_ws::WORKSPACE_FOCUSED_URGENT; workspace_mask = make_mask(state::FOCUSED, state::URGENT);
break; break;
case 'f': case 'f':
workspace_flag = state_ws::WORKSPACE_EMPTY; workspace_mask = make_mask(state::EMPTY);
break; break;
case 'o': case 'o':
workspace_flag = state_ws::WORKSPACE_OCCUPIED; workspace_mask = make_mask(state::OCCUPIED);
break; break;
case 'u': case 'u':
workspace_flag = state_ws::WORKSPACE_URGENT; workspace_mask = make_mask(state::URGENT);
break; break;
case 'L': case 'L':
switch (value[0]) { switch (value[0]) {
case 0: case 0:
break; break;
case 'M': case 'M':
mode_flag = state_mode::MODE_LAYOUT_MONOCLE; mode_flag = mode::LAYOUT_MONOCLE;
break; break;
case 'T': case 'T':
mode_flag = state_mode::MODE_LAYOUT_TILED; mode_flag = mode::LAYOUT_TILED;
break; break;
default: default:
m_log.warn("%s: Undefined L => '%s'", name(), value); m_log.warn("%s: Undefined L => '%s'", name(), value);
@ -242,10 +280,10 @@ namespace modules {
case 'T': case 'T':
break; break;
case '=': case '=':
mode_flag = state_mode::MODE_STATE_FULLSCREEN; mode_flag = mode::STATE_FULLSCREEN;
break; break;
case 'F': case 'F':
mode_flag = state_mode::MODE_STATE_FLOATING; mode_flag = mode::STATE_FLOATING;
break; break;
default: default:
m_log.warn("%s: Undefined T => '%s'", name(), value); m_log.warn("%s: Undefined T => '%s'", name(), value);
@ -262,19 +300,19 @@ namespace modules {
case 0: case 0:
break; break;
case 'L': case 'L':
mode_flag = state_mode::MODE_NODE_LOCKED; mode_flag = mode::NODE_LOCKED;
break; break;
case 'S': case 'S':
mode_flag = state_mode::MODE_NODE_STICKY; mode_flag = mode::NODE_STICKY;
break; break;
case 'P': case 'P':
mode_flag = state_mode::MODE_NODE_PRIVATE; mode_flag = mode::NODE_PRIVATE;
break; break;
default: default:
m_log.warn("%s: Undefined G => '%s'", name(), value.substr(i, 1)); m_log.warn("%s: Undefined G => '%s'", name(), value.substr(i, 1));
} }
if (mode_flag != state_mode::MODE_NONE && !m_modelabels.empty()) { if (mode_flag != mode::NONE && !m_modelabels.empty()) {
m_monitors.back()->modes.emplace_back(m_modelabels.find(mode_flag)->second->clone()); m_monitors.back()->modes.emplace_back(m_modelabels.find(mode_flag)->second->clone());
} }
} }
@ -284,28 +322,21 @@ namespace modules {
m_log.warn("%s: Undefined tag => '%s'", name(), tag.substr(0, 1)); m_log.warn("%s: Undefined tag => '%s'", name(), tag.substr(0, 1));
} }
if (workspace_flag != state_ws::WORKSPACE_NONE && m_formatter->has(TAG_LABEL_STATE)) { if (workspace_mask && m_formatter->has(TAG_LABEL_STATE)) {
auto icon = m_icons->get(value, DEFAULT_WS_ICON); auto icon = m_icons->get(value, DEFAULT_ICON);
auto label = m_statelabels.find(workspace_flag)->second->clone(); auto label = m_statelabels.at(workspace_mask)->clone();
if (!m_monitors.back()->focused) { if (!m_monitors.back()->focused) {
label->replace_defined_values(m_statelabels.find(state_ws::WORKSPACE_DIMMED)->second); if (m_statelabels[make_mask(state::DIMMED)])
switch (workspace_flag) { label->replace_defined_values(m_statelabels[make_mask(state::DIMMED)]);
case state_ws::WORKSPACE_ACTIVE: if (workspace_mask & make_mask(state::EMPTY))
label->replace_defined_values(m_statelabels.find(state_ws::WORKSPACE_DIMMED_ACTIVE)->second); label->replace_defined_values(m_statelabels[make_mask(state::DIMMED, state::EMPTY)]);
break; if (workspace_mask & make_mask(state::OCCUPIED))
case state_ws::WORKSPACE_OCCUPIED: label->replace_defined_values(m_statelabels[make_mask(state::DIMMED, state::OCCUPIED)]);
label->replace_defined_values(m_statelabels.find(state_ws::WORKSPACE_DIMMED_OCCUPIED)->second); if (workspace_mask & make_mask(state::FOCUSED))
break; label->replace_defined_values(m_statelabels[make_mask(state::DIMMED, state::FOCUSED)]);
case state_ws::WORKSPACE_URGENT: if (workspace_mask & make_mask(state::URGENT))
label->replace_defined_values(m_statelabels.find(state_ws::WORKSPACE_DIMMED_URGENT)->second); label->replace_defined_values(m_statelabels[make_mask(state::DIMMED, state::URGENT)]);
break;
case state_ws::WORKSPACE_EMPTY:
label->replace_defined_values(m_statelabels.find(state_ws::WORKSPACE_DIMMED_EMPTY)->second);
break;
default:
break;
}
} }
label->reset_tokens(); label->reset_tokens();
@ -313,10 +344,10 @@ namespace modules {
label->replace_token("%icon%", icon->get()); label->replace_token("%icon%", icon->get());
label->replace_token("%index%", to_string(++workspace_n)); label->replace_token("%index%", to_string(++workspace_n));
m_monitors.back()->workspaces.emplace_back(make_pair(workspace_flag, move(label))); m_monitors.back()->workspaces.emplace_back(workspace_mask, move(label));
} }
if (mode_flag != state_mode::MODE_NONE && !m_modelabels.empty()) { if (mode_flag != mode::NONE && !m_modelabels.empty()) {
m_monitors.back()->modes.emplace_back(m_modelabels.find(mode_flag)->second->clone()); m_monitors.back()->modes.emplace_back(m_modelabels.find(mode_flag)->second->clone());
} }
} }
@ -339,7 +370,7 @@ namespace modules {
if (tag == TAG_LABEL_MONITOR) { if (tag == TAG_LABEL_MONITOR) {
builder->node(m_monitors[m_index]->label); builder->node(m_monitors[m_index]->label);
return true; return true;
} else if (tag == TAG_LABEL_STATE) { } else if (tag == TAG_LABEL_STATE && !m_monitors[m_index]->workspaces.empty()) {
int workspace_n = 0; int workspace_n = 0;
if (m_scroll) { if (m_scroll) {
@ -350,12 +381,7 @@ namespace modules {
for (auto&& ws : m_monitors[m_index]->workspaces) { for (auto&& ws : m_monitors[m_index]->workspaces) {
if (ws.second.get()) { if (ws.second.get()) {
if (m_click) { if (m_click) {
string event{EVENT_CLICK}; builder->cmd(mousebtn::LEFT, EVENT_CLICK + to_string(m_index) + "+" + to_string(++workspace_n));
event += to_string(m_index);
event += "+";
event += to_string(++workspace_n);
builder->cmd(mousebtn::LEFT, event);
builder->node(ws.second); builder->node(ws.second);
builder->cmd_close(); builder->cmd_close();
} else { } else {
@ -371,7 +397,7 @@ namespace modules {
} }
return workspace_n > 0; return workspace_n > 0;
} else if (tag == TAG_LABEL_MODE && m_monitors[m_index]->focused) { } else if (tag == TAG_LABEL_MODE && m_monitors[m_index]->focused && !m_monitors[m_index]->modes.empty()) {
int modes_n = 0; int modes_n = 0;
for (auto&& mode : m_monitors[m_index]->modes) { for (auto&& mode : m_monitors[m_index]->modes) {