feat(i3): Add mode label
This commit is contained in:
parent
a43309df9f
commit
9cadb681d4
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,7 +1,7 @@
|
|||||||
[submodule "lib/i3ipcpp"]
|
[submodule "lib/i3ipcpp"]
|
||||||
path = lib/i3ipcpp
|
path = lib/i3ipcpp
|
||||||
url = https://github.com/jaagr/i3ipcpp
|
url = https://github.com/jaagr/i3ipcpp
|
||||||
branch = v0.5.1
|
branch = v0.6.0
|
||||||
[submodule "lib/xpp"]
|
[submodule "lib/xpp"]
|
||||||
path = lib/xpp
|
path = lib/xpp
|
||||||
url = https://github.com/jaagr/xpp
|
url = https://github.com/jaagr/xpp
|
||||||
|
@ -11,33 +11,27 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
// meta types {{{
|
|
||||||
|
|
||||||
enum class i3_flag {
|
|
||||||
WORKSPACE_NONE,
|
|
||||||
WORKSPACE_FOCUSED,
|
|
||||||
WORKSPACE_UNFOCUSED,
|
|
||||||
WORKSPACE_VISIBLE,
|
|
||||||
WORKSPACE_URGENT,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct i3_workspace {
|
|
||||||
int index;
|
|
||||||
i3_flag flag;
|
|
||||||
label_t label;
|
|
||||||
|
|
||||||
i3_workspace(int index_, i3_flag flag_, label_t&& label_)
|
|
||||||
: index(index_), flag(flag_), label(forward<decltype(label_)>(label_)) {}
|
|
||||||
|
|
||||||
operator bool();
|
|
||||||
};
|
|
||||||
|
|
||||||
using i3_workspace_t = unique_ptr<i3_workspace>;
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
class i3_module : public event_module<i3_module> {
|
class i3_module : public event_module<i3_module> {
|
||||||
public:
|
public:
|
||||||
|
enum class state {
|
||||||
|
NONE,
|
||||||
|
FOCUSED,
|
||||||
|
UNFOCUSED,
|
||||||
|
VISIBLE,
|
||||||
|
URGENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct workspace {
|
||||||
|
explicit workspace(int index, state state_, label_t&& label)
|
||||||
|
: index(index), state(state_), label(forward<label_t>(label)) {}
|
||||||
|
|
||||||
|
operator bool();
|
||||||
|
|
||||||
|
int index;
|
||||||
|
state state;
|
||||||
|
label_t label;
|
||||||
|
};
|
||||||
|
|
||||||
using event_module::event_module;
|
using event_module::event_module;
|
||||||
|
|
||||||
void setup();
|
void setup();
|
||||||
@ -51,19 +45,26 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr auto DEFAULT_WS_ICON = "ws-icon-default";
|
static constexpr const char* DEFAULT_TAGS{"<label-state> <label-mode>"};
|
||||||
static constexpr auto DEFAULT_WS_LABEL = "%icon% %name%";
|
static constexpr const char* DEFAULT_MODE{"default"};
|
||||||
static constexpr auto TAG_LABEL_STATE = "<label-state>";
|
static constexpr const char* DEFAULT_WS_ICON{"ws-icon-default"};
|
||||||
|
static constexpr const char* DEFAULT_WS_LABEL{"%icon% %name%"};
|
||||||
|
|
||||||
static constexpr auto EVENT_PREFIX = "i3";
|
static constexpr const char* TAG_LABEL_STATE{"<label-state>"};
|
||||||
static constexpr auto EVENT_CLICK = "i3-wsfocus-";
|
static constexpr const char* TAG_LABEL_MODE{"<label-mode>"};
|
||||||
static constexpr auto EVENT_SCROLL_UP = "i3-wsnext";
|
|
||||||
static constexpr auto EVENT_SCROLL_DOWN = "i3-wsprev";
|
|
||||||
|
|
||||||
map<i3_flag, label_t> m_statelabels;
|
static constexpr const char* EVENT_PREFIX{"i3"};
|
||||||
vector<i3_workspace_t> m_workspaces;
|
static constexpr const char* EVENT_CLICK{"i3-wsfocus-"};
|
||||||
|
static constexpr const char* EVENT_SCROLL_UP{"i3-wsnext"};
|
||||||
|
static constexpr const char* EVENT_SCROLL_DOWN{"i3-wsprev"};
|
||||||
|
|
||||||
|
map<state, label_t> m_statelabels;
|
||||||
|
vector<unique_ptr<workspace>> m_workspaces;
|
||||||
iconset_t m_icons;
|
iconset_t m_icons;
|
||||||
|
|
||||||
|
label_t m_modelabel;
|
||||||
|
bool m_modeactive{false};
|
||||||
|
|
||||||
bool m_click = true;
|
bool m_click = true;
|
||||||
bool m_scroll = true;
|
bool m_scroll = true;
|
||||||
bool m_indexsort = false;
|
bool m_indexsort = false;
|
||||||
@ -71,7 +72,7 @@ namespace modules {
|
|||||||
bool m_strip_wsnumbers = false;
|
bool m_strip_wsnumbers = false;
|
||||||
size_t m_wsname_maxlen = 0;
|
size_t m_wsname_maxlen = 0;
|
||||||
|
|
||||||
i3_util::connection_t m_ipc;
|
unique_ptr<i3_util::connection_t> m_ipc;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit a96542431949cb5d429df1078d9ba3ad28be371b
|
Subproject commit 8d78ec8cb08f66874082a8d9166793e478682d97
|
@ -1,9 +1,9 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include "modules/i3.hpp"
|
|
||||||
|
|
||||||
#include "drawtypes/iconset.hpp"
|
#include "drawtypes/iconset.hpp"
|
||||||
#include "drawtypes/label.hpp"
|
#include "drawtypes/label.hpp"
|
||||||
|
#include "modules/i3.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
#include "modules/meta/base.inl"
|
#include "modules/meta/base.inl"
|
||||||
#include "modules/meta/event_module.inl"
|
#include "modules/meta/event_module.inl"
|
||||||
@ -14,11 +14,19 @@ namespace modules {
|
|||||||
template class module<i3_module>;
|
template class module<i3_module>;
|
||||||
template class event_module<i3_module>;
|
template class event_module<i3_module>;
|
||||||
|
|
||||||
i3_workspace::operator bool() {
|
i3_module::workspace::operator bool() {
|
||||||
return label && *label;
|
return label && *label;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i3_module::setup() { // {{{
|
void i3_module::setup() {
|
||||||
|
auto socket_path = i3ipc::get_socketpath();
|
||||||
|
|
||||||
|
if (!file_util::exists(socket_path)) {
|
||||||
|
throw module_error("Could not find socket: " + (socket_path.empty() ? "<empty>" : socket_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ipc = make_unique<i3ipc::connection>();
|
||||||
|
|
||||||
// Load configuration values
|
// Load configuration values
|
||||||
GET_CONFIG_VALUE(name(), m_click, "enable-click");
|
GET_CONFIG_VALUE(name(), m_click, "enable-click");
|
||||||
GET_CONFIG_VALUE(name(), m_scroll, "enable-scroll");
|
GET_CONFIG_VALUE(name(), m_scroll, "enable-scroll");
|
||||||
@ -28,17 +36,21 @@ namespace modules {
|
|||||||
GET_CONFIG_VALUE(name(), m_wsname_maxlen, "wsname-maxlen");
|
GET_CONFIG_VALUE(name(), m_wsname_maxlen, "wsname-maxlen");
|
||||||
|
|
||||||
// Add formats and create components
|
// Add formats and create components
|
||||||
m_formatter->add(DEFAULT_FORMAT, TAG_LABEL_STATE, {TAG_LABEL_STATE});
|
m_formatter->add(DEFAULT_FORMAT, DEFAULT_TAGS, {TAG_LABEL_STATE, TAG_LABEL_MODE});
|
||||||
|
|
||||||
if (m_formatter->has(TAG_LABEL_STATE)) {
|
if (m_formatter->has(TAG_LABEL_STATE)) {
|
||||||
m_statelabels.insert(make_pair(
|
|
||||||
i3_flag::WORKSPACE_FOCUSED, load_optional_label(m_conf, name(), "label-focused", DEFAULT_WS_LABEL)));
|
|
||||||
m_statelabels.insert(make_pair(
|
|
||||||
i3_flag::WORKSPACE_UNFOCUSED, load_optional_label(m_conf, name(), "label-unfocused", DEFAULT_WS_LABEL)));
|
|
||||||
m_statelabels.insert(make_pair(
|
|
||||||
i3_flag::WORKSPACE_VISIBLE, load_optional_label(m_conf, name(), "label-visible", DEFAULT_WS_LABEL)));
|
|
||||||
m_statelabels.insert(
|
m_statelabels.insert(
|
||||||
make_pair(i3_flag::WORKSPACE_URGENT, load_optional_label(m_conf, name(), "label-urgent", DEFAULT_WS_LABEL)));
|
make_pair(state::FOCUSED, load_optional_label(m_conf, name(), "label-focused", DEFAULT_WS_LABEL)));
|
||||||
|
m_statelabels.insert(
|
||||||
|
make_pair(state::UNFOCUSED, load_optional_label(m_conf, name(), "label-unfocused", DEFAULT_WS_LABEL)));
|
||||||
|
m_statelabels.insert(
|
||||||
|
make_pair(state::VISIBLE, load_optional_label(m_conf, name(), "label-visible", DEFAULT_WS_LABEL)));
|
||||||
|
m_statelabels.insert(
|
||||||
|
make_pair(state::URGENT, load_optional_label(m_conf, name(), "label-urgent", DEFAULT_WS_LABEL)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_formatter->has(TAG_LABEL_MODE)) {
|
||||||
|
m_modelabel = load_optional_label(m_conf, name(), "label-mode", "%mode%");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_icons = make_shared<iconset>();
|
m_icons = make_shared<iconset>();
|
||||||
@ -52,29 +64,44 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_ipc.subscribe(i3ipc::ET_WORKSPACE);
|
if (m_modelabel) {
|
||||||
m_ipc.prepare_to_event_handling();
|
m_ipc->on_mode_event = [this](const i3ipc::mode_t& mode) {
|
||||||
} catch (std::exception& err) {
|
m_modeactive = (mode.change != DEFAULT_MODE);
|
||||||
|
if (m_modeactive) {
|
||||||
|
m_modelabel->reset_tokens();
|
||||||
|
m_modelabel->replace_token("%mode%", mode.change);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
m_ipc->subscribe(i3ipc::ET_WORKSPACE | i3ipc::ET_MODE);
|
||||||
|
} catch (const exception& err) {
|
||||||
throw module_error(err.what());
|
throw module_error(err.what());
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
|
|
||||||
void i3_module::stop() { // {{{
|
void i3_module::stop() {
|
||||||
try {
|
try {
|
||||||
m_log.info("%s: Disconnecting from sockets", name());
|
if (m_ipc) {
|
||||||
shutdown(m_ipc.get_event_socket_fd(), SHUT_RDWR);
|
m_log.info("%s: Disconnecting from socket", name());
|
||||||
shutdown(m_ipc.get_main_socket_fd(), SHUT_RDWR);
|
shutdown(m_ipc->get_event_socket_fd(), SHUT_RDWR);
|
||||||
|
shutdown(m_ipc->get_main_socket_fd(), SHUT_RDWR);
|
||||||
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
event_module::stop();
|
event_module::stop();
|
||||||
} // }}}
|
}
|
||||||
|
|
||||||
bool i3_module::has_event() { // {{{
|
bool i3_module::has_event() {
|
||||||
return m_ipc.handle_event();
|
try {
|
||||||
} // }}}
|
m_ipc->handle_event();
|
||||||
|
return true;
|
||||||
|
} catch (const exception& err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool i3_module::update() { // {{{
|
bool i3_module::update() {
|
||||||
m_workspaces.clear();
|
m_workspaces.clear();
|
||||||
i3_util::connection_t ipc;
|
i3_util::connection_t ipc;
|
||||||
|
|
||||||
@ -83,9 +110,9 @@ namespace modules {
|
|||||||
vector<shared_ptr<i3ipc::workspace_t>> sorted = workspaces;
|
vector<shared_ptr<i3ipc::workspace_t>> sorted = workspaces;
|
||||||
string focused_output;
|
string focused_output;
|
||||||
|
|
||||||
for (auto&& workspace : workspaces) {
|
for (auto&& ws : workspaces) {
|
||||||
if (workspace->focused) {
|
if (ws->focused) {
|
||||||
focused_output = workspace->output;
|
focused_output = ws->output;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,23 +126,23 @@ namespace modules {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto&& workspace : sorted) {
|
for (auto&& ws : sorted) {
|
||||||
if (m_pinworkspaces && workspace->output != m_bar.monitor->name) {
|
if (m_pinworkspaces && ws->output != m_bar.monitor->name) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto flag = i3_flag::WORKSPACE_NONE;
|
auto state = state::NONE;
|
||||||
if (workspace->focused) {
|
if (ws->focused) {
|
||||||
flag = i3_flag::WORKSPACE_FOCUSED;
|
state = state::FOCUSED;
|
||||||
} else if (workspace->urgent) {
|
} else if (ws->urgent) {
|
||||||
flag = i3_flag::WORKSPACE_URGENT;
|
state = state::URGENT;
|
||||||
} else if (!workspace->visible || (workspace->visible && workspace->output != focused_output)) {
|
} else if (!ws->visible || (ws->visible && ws->output != focused_output)) {
|
||||||
flag = i3_flag::WORKSPACE_UNFOCUSED;
|
state = state::UNFOCUSED;
|
||||||
} else {
|
} else {
|
||||||
flag = i3_flag::WORKSPACE_VISIBLE;
|
state = state::VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
string wsname{workspace->name};
|
string wsname{ws->name};
|
||||||
|
|
||||||
// Remove workspace numbers "0:"
|
// Remove workspace numbers "0:"
|
||||||
if (m_strip_wsnumbers) {
|
if (m_strip_wsnumbers) {
|
||||||
@ -130,53 +157,55 @@ namespace modules {
|
|||||||
wsname.erase(m_wsname_maxlen);
|
wsname.erase(m_wsname_maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto icon = m_icons->get(workspace->name, DEFAULT_WS_ICON);
|
auto icon = m_icons->get(ws->name, DEFAULT_WS_ICON);
|
||||||
auto label = m_statelabels.find(flag)->second->clone();
|
auto label = m_statelabels.find(state)->second->clone();
|
||||||
|
|
||||||
label->reset_tokens();
|
label->reset_tokens();
|
||||||
label->replace_token("%output%", workspace->output);
|
label->replace_token("%output%", ws->output);
|
||||||
label->replace_token("%name%", wsname);
|
label->replace_token("%name%", wsname);
|
||||||
label->replace_token("%icon%", icon->get());
|
label->replace_token("%icon%", icon->get());
|
||||||
label->replace_token("%index%", to_string(workspace->num));
|
label->replace_token("%index%", to_string(ws->num));
|
||||||
m_workspaces.emplace_back(make_unique<i3_workspace>(workspace->num, flag, move(label)));
|
m_workspaces.emplace_back(make_unique<workspace>(ws->num, state, move(label)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (const std::exception& err) {
|
} catch (const exception& err) {
|
||||||
m_log.err("%s: %s", name(), err.what());
|
m_log.err("%s: %s", name(), err.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // }}}
|
}
|
||||||
|
|
||||||
bool i3_module::build(builder* builder, const string& tag) const { // {{{
|
bool i3_module::build(builder* builder, const string& tag) const {
|
||||||
if (tag != TAG_LABEL_STATE) {
|
if (tag == TAG_LABEL_MODE && m_modeactive) {
|
||||||
|
builder->node(m_modelabel);
|
||||||
|
} else if (tag == TAG_LABEL_STATE && !m_workspaces.empty()) {
|
||||||
|
if (m_scroll) {
|
||||||
|
builder->cmd(mousebtn::SCROLL_DOWN, EVENT_SCROLL_DOWN);
|
||||||
|
builder->cmd(mousebtn::SCROLL_UP, EVENT_SCROLL_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto&& ws : m_workspaces) {
|
||||||
|
if (m_click) {
|
||||||
|
builder->cmd(mousebtn::LEFT, string{EVENT_CLICK} + to_string(ws->index));
|
||||||
|
builder->node(ws->label);
|
||||||
|
builder->cmd_close();
|
||||||
|
} else {
|
||||||
|
builder->node(ws->label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_scroll) {
|
||||||
|
builder->cmd_close();
|
||||||
|
builder->cmd_close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_scroll) {
|
|
||||||
builder->cmd(mousebtn::SCROLL_DOWN, EVENT_SCROLL_DOWN);
|
|
||||||
builder->cmd(mousebtn::SCROLL_UP, EVENT_SCROLL_UP);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto&& ws : m_workspaces) {
|
|
||||||
if (m_click) {
|
|
||||||
builder->cmd(mousebtn::LEFT, string{EVENT_CLICK} + to_string(ws->index));
|
|
||||||
builder->node(ws->label);
|
|
||||||
builder->cmd_close();
|
|
||||||
} else {
|
|
||||||
builder->node(ws->label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_scroll) {
|
|
||||||
builder->cmd_close();
|
|
||||||
builder->cmd_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // }}}
|
}
|
||||||
|
|
||||||
bool i3_module::handle_event(string cmd) { // {{{
|
bool i3_module::handle_event(string cmd) {
|
||||||
if (cmd.compare(0, 2, EVENT_PREFIX) != 0) {
|
if (cmd.compare(0, 2, EVENT_PREFIX) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -194,12 +223,12 @@ namespace modules {
|
|||||||
m_log.info("%s: Sending workspace next command to ipc handler", name());
|
m_log.info("%s: Sending workspace next command to ipc handler", name());
|
||||||
ipc.send_command("workspace prev_on_output");
|
ipc.send_command("workspace prev_on_output");
|
||||||
}
|
}
|
||||||
} catch (const std::exception& err) {
|
} catch (const exception& err) {
|
||||||
m_log.err("%s: %s", name(), err.what());
|
m_log.err("%s: %s", name(), err.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} // }}}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
Loading…
Reference in New Issue
Block a user