2018-08-08 21:54:58 +00:00
|
|
|
#include "modules/workspaces.hpp"
|
|
|
|
#include "ipc/client.hpp"
|
|
|
|
|
2018-08-09 10:05:48 +00:00
|
|
|
waybar::modules::Workspaces::Workspaces(Bar &bar)
|
2018-08-09 18:22:01 +00:00
|
|
|
: _bar(bar), _thread(nullptr), _box(Gtk::manage(new Gtk::Box))
|
2018-08-08 21:54:58 +00:00
|
|
|
{
|
2018-08-09 08:50:16 +00:00
|
|
|
_box->get_style_context()->add_class("workspaces");
|
2018-08-08 21:54:58 +00:00
|
|
|
std::string socketPath = get_socketpath();
|
|
|
|
_ipcSocketfd = ipc_open_socket(socketPath);
|
|
|
|
_ipcEventSocketfd = ipc_open_socket(socketPath);
|
|
|
|
const char *subscribe = "[ \"workspace\", \"mode\" ]";
|
|
|
|
uint32_t len = strlen(subscribe);
|
|
|
|
ipc_single_command(_ipcEventSocketfd, IPC_SUBSCRIBE, subscribe, &len);
|
2018-08-08 23:10:07 +00:00
|
|
|
_idle_timer =
|
|
|
|
org_kde_kwin_idle_get_idle_timeout(_bar.client.idle_manager,
|
|
|
|
_bar.client.seat, 10000); // 10 seconds
|
2018-08-09 18:22:01 +00:00
|
|
|
static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = {
|
|
|
|
.idle = _handle_idle,
|
|
|
|
.resumed = _handle_resume,
|
|
|
|
};
|
2018-08-08 23:10:07 +00:00
|
|
|
org_kde_kwin_idle_timeout_add_listener(_idle_timer,
|
|
|
|
&idle_timer_listener, this);
|
2018-08-09 18:22:01 +00:00
|
|
|
_updateThread();
|
2018-08-08 21:54:58 +00:00
|
|
|
}
|
|
|
|
|
2018-08-09 10:05:48 +00:00
|
|
|
auto waybar::modules::Workspaces::update() -> void
|
2018-08-08 21:54:58 +00:00
|
|
|
{
|
|
|
|
Json::Value workspaces = _getWorkspaces();
|
2018-08-09 10:25:01 +00:00
|
|
|
bool hided = false;
|
2018-08-08 21:54:58 +00:00
|
|
|
for (auto it = _buttons.begin(); it != _buttons.end(); ++it) {
|
|
|
|
auto ws = std::find_if(workspaces.begin(), workspaces.end(),
|
|
|
|
[it](auto node) -> bool { return node["num"].asInt() == it->first; });
|
|
|
|
if (ws == workspaces.end()) {
|
|
|
|
it->second.hide();
|
2018-08-09 10:25:01 +00:00
|
|
|
hided = true;
|
2018-08-08 21:54:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto node : workspaces) {
|
|
|
|
auto it = _buttons.find(node["num"].asInt());
|
|
|
|
if (it == _buttons.end()) {
|
|
|
|
_addWorkspace(node);
|
|
|
|
} else {
|
|
|
|
auto styleContext = it->second.get_style_context();
|
|
|
|
bool isCurrent = node["focused"].asBool();
|
|
|
|
if (styleContext->has_class("current") && !isCurrent) {
|
|
|
|
styleContext->remove_class("current");
|
|
|
|
} else if (!styleContext->has_class("current") && isCurrent) {
|
|
|
|
styleContext->add_class("current");
|
|
|
|
}
|
2018-08-09 10:25:01 +00:00
|
|
|
if (hided) {
|
|
|
|
_box->reorder_child(it->second, node["num"].asInt() - 1);
|
|
|
|
}
|
2018-08-08 21:54:58 +00:00
|
|
|
it->second.show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-09 18:22:01 +00:00
|
|
|
void waybar::modules::Workspaces::_updateThread()
|
|
|
|
{
|
|
|
|
_thread = new waybar::util::SleeperThread([this] {
|
|
|
|
update();
|
|
|
|
_thread->sleep_for(waybar::chrono::milliseconds(250));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void waybar::modules::Workspaces::_handle_idle(void *data,
|
|
|
|
struct org_kde_kwin_idle_timeout *timer) {
|
|
|
|
auto o = reinterpret_cast<waybar::modules::Workspaces *>(data);
|
|
|
|
if (o->_thread) {
|
|
|
|
delete o->_thread;
|
|
|
|
o->_thread = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void waybar::modules::Workspaces::_handle_resume(void *data,
|
|
|
|
struct org_kde_kwin_idle_timeout *timer) {
|
|
|
|
auto o = reinterpret_cast<waybar::modules::Workspaces *>(data);
|
|
|
|
if (!o->_thread) {
|
|
|
|
o->_updateThread();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-09 10:05:48 +00:00
|
|
|
void waybar::modules::Workspaces::_addWorkspace(Json::Value node)
|
2018-08-08 21:54:58 +00:00
|
|
|
{
|
|
|
|
auto pair = _buttons.emplace(node["num"].asInt(), node["name"].asString());
|
|
|
|
auto &button = pair.first->second;
|
|
|
|
button.set_relief(Gtk::RELIEF_NONE);
|
|
|
|
button.signal_clicked().connect([this, pair] {
|
|
|
|
auto value = fmt::format("workspace \"{}\"", pair.first->first);
|
|
|
|
uint32_t size = value.size();
|
|
|
|
ipc_single_command(_ipcSocketfd, IPC_COMMAND, value.c_str(), &size);
|
|
|
|
});
|
|
|
|
_box->pack_start(button, false, false, 0);
|
2018-08-09 09:12:46 +00:00
|
|
|
_box->reorder_child(button, node["num"].asInt() - 1);
|
2018-08-08 21:54:58 +00:00
|
|
|
if (node["focused"].asBool()) {
|
|
|
|
button.get_style_context()->add_class("current");
|
|
|
|
}
|
|
|
|
button.show();
|
|
|
|
}
|
|
|
|
|
2018-08-09 10:05:48 +00:00
|
|
|
Json::Value waybar::modules::Workspaces::_getWorkspaces()
|
2018-08-08 21:54:58 +00:00
|
|
|
{
|
|
|
|
uint32_t len = 0;
|
|
|
|
Json::Value root;
|
|
|
|
Json::CharReaderBuilder builder;
|
|
|
|
Json::CharReader* reader = builder.newCharReader();
|
|
|
|
std::string err;
|
|
|
|
std::string str = ipc_single_command(_ipcSocketfd, IPC_GET_WORKSPACES,
|
|
|
|
nullptr, &len);
|
|
|
|
bool res = reader->parse(str.c_str(), str.c_str() + str.size(), &root, &err);
|
|
|
|
delete reader;
|
|
|
|
if (!res) {
|
|
|
|
std::cerr << err << std::endl;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
|
2018-08-09 10:05:48 +00:00
|
|
|
waybar::modules::Workspaces::operator Gtk::Widget &() {
|
2018-08-08 21:54:58 +00:00
|
|
|
return *_box;
|
|
|
|
}
|