fix(workspaces): avoid mutex block

pull/272/head
Alex 2019-04-19 12:11:55 +02:00
parent 171ecd53aa
commit e77c155ede
3 changed files with 43 additions and 33 deletions

View File

@ -26,9 +26,11 @@ class Workspaces : public IModule {
void onButtonReady(const Json::Value&, Gtk::Button&); void onButtonReady(const Json::Value&, Gtk::Button&);
std::string getIcon(const std::string&, const Json::Value&); std::string getIcon(const std::string&, const Json::Value&);
bool handleScroll(GdkEventScroll*); bool handleScroll(GdkEventScroll*);
const std::string getCycleWorkspace(uint8_t current, bool prev) const; const std::string getCycleWorkspace(const Json::Value& workspaces, uint8_t current,
uint16_t getWorkspaceIndex(const std::string& name) const; bool prev) const;
uint16_t getWorkspaceIndex(const Json::Value& workspaces, const std::string& name) const;
std::string trimWorkspaceName(std::string); std::string trimWorkspaceName(std::string);
const Json::Value getWorkspaces();
const Bar& bar_; const Bar& bar_;
const Json::Value& config_; const Json::Value& config_;

View File

@ -77,11 +77,11 @@ struct Ipc::ipc_response Ipc::recv(int fd) const {
while (total < ipc_header_size_) { while (total < ipc_header_size_) {
auto res = ::recv(fd, header.data() + total, ipc_header_size_ - total, 0); auto res = ::recv(fd, header.data() + total, ipc_header_size_ - total, 0);
if (res <= 0) { if (fd_event_ == -1 || fd_ == -1) {
if (res <= 0 && (fd_event_ == -1 || fd_ == -1)) {
// IPC is closed so just return an empty response // IPC is closed so just return an empty response
return {0, 0, ""}; return {0, 0, ""};
} }
if (res <= 0) {
throw std::runtime_error("Unable to receive IPC header"); throw std::runtime_error("Unable to receive IPC header");
} }
total += res; total += res;

View File

@ -25,10 +25,15 @@ void Workspaces::onCmd(const struct Ipc::ipc_response res) {
} }
} }
const Json::Value Workspaces::getWorkspaces() {
std::lock_guard<std::mutex> lock(mutex_);
return workspaces_;
}
void Workspaces::worker() { void Workspaces::worker() {
thread_ = [this] { thread_ = [this] {
try { try {
if (!workspaces_.empty()) { if (!getWorkspaces().empty()) {
ipc_.handleEvent(); ipc_.handleEvent();
} }
if (thread_.isRunning()) { if (thread_.isRunning()) {
@ -42,12 +47,12 @@ void Workspaces::worker() {
auto Workspaces::update() -> void { auto Workspaces::update() -> void {
bool needReorder = false; bool needReorder = false;
std::lock_guard<std::mutex> lock(mutex_); auto workspaces = getWorkspaces();
for (auto it = buttons_.begin(); it != buttons_.end();) { for (auto it = buttons_.begin(); it != buttons_.end();) {
auto ws = std::find_if(workspaces_.begin(), workspaces_.end(), [it](auto node) -> bool { auto ws = std::find_if(workspaces.begin(), workspaces.end(), [it](auto node) -> bool {
return node["name"].asString() == it->first; return node["name"].asString() == it->first;
}); });
if (ws == workspaces_.end() || if (ws == workspaces.end() ||
(!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) { (!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) {
it = buttons_.erase(it); it = buttons_.erase(it);
needReorder = true; needReorder = true;
@ -55,7 +60,7 @@ auto Workspaces::update() -> void {
++it; ++it;
} }
} }
for (auto const &node : workspaces_) { for (auto const &node : workspaces) {
if (!config_["all-outputs"].asBool() && bar_.output->name != node["output"].asString()) { if (!config_["all-outputs"].asBool() && bar_.output->name != node["output"].asString()) {
continue; continue;
} }
@ -81,7 +86,7 @@ auto Workspaces::update() -> void {
button.get_style_context()->remove_class("urgent"); button.get_style_context()->remove_class("urgent");
} }
if (needReorder) { if (needReorder) {
box_.reorder_child(button, getWorkspaceIndex(node["name"].asString())); box_.reorder_child(button, getWorkspaceIndex(workspaces, node["name"].asString()));
} }
auto icon = getIcon(node["name"].asString(), node); auto icon = getIcon(node["name"].asString(), node);
std::string output = icon; std::string output = icon;
@ -132,7 +137,8 @@ void Workspaces::addWorkspace(const Json::Value &node) {
button.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); button.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
button.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll)); button.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
} }
box_.reorder_child(button, getWorkspaceIndex(node["name"].asString())); auto workspaces = getWorkspaces();
box_.reorder_child(button, getWorkspaceIndex(workspaces, node["name"].asString()));
if (node["focused"].asBool()) { if (node["focused"].asBool()) {
button.get_style_context()->add_class("focused"); button.get_style_context()->add_class("focused");
} }
@ -165,35 +171,35 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
if (scrolling_) { if (scrolling_) {
return false; return false;
} }
std::lock_guard<std::mutex> lock(mutex_); auto workspaces = getWorkspaces();
uint8_t idx; uint8_t idx;
scrolling_ = true; scrolling_ = true;
for (idx = 0; idx < workspaces_.size(); idx += 1) { for (idx = 0; idx < workspaces.size(); idx += 1) {
if (workspaces_[idx]["focused"].asBool()) { if (workspaces[idx]["focused"].asBool()) {
break; break;
} }
} }
if (idx == workspaces_.size()) { if (idx == workspaces.size()) {
scrolling_ = false; scrolling_ = false;
return false; return false;
} }
std::string name; std::string name;
if (e->direction == GDK_SCROLL_UP) { if (e->direction == GDK_SCROLL_UP) {
name = getCycleWorkspace(idx, true); name = getCycleWorkspace(workspaces, idx, true);
} }
if (e->direction == GDK_SCROLL_DOWN) { if (e->direction == GDK_SCROLL_DOWN) {
name = getCycleWorkspace(idx, false); name = getCycleWorkspace(workspaces, idx, false);
} }
if (e->direction == GDK_SCROLL_SMOOTH) { if (e->direction == GDK_SCROLL_SMOOTH) {
gdouble delta_x, delta_y; gdouble delta_x, delta_y;
gdk_event_get_scroll_deltas(reinterpret_cast<const GdkEvent *>(e), &delta_x, &delta_y); gdk_event_get_scroll_deltas(reinterpret_cast<const GdkEvent *>(e), &delta_x, &delta_y);
if (delta_y < 0) { if (delta_y < 0) {
name = getCycleWorkspace(idx, true); name = getCycleWorkspace(workspaces, idx, true);
} else if (delta_y > 0) { } else if (delta_y > 0) {
name = getCycleWorkspace(idx, false); name = getCycleWorkspace(workspaces, idx, false);
} }
} }
if (name.empty() || name == workspaces_[idx]["name"].asString()) { if (name.empty() || name == workspaces[idx]["name"].asString()) {
scrolling_ = false; scrolling_ = false;
return false; return false;
} }
@ -202,24 +208,25 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
return true; return true;
} }
const std::string Workspaces::getCycleWorkspace(uint8_t focused_workspace, bool prev) const { const std::string Workspaces::getCycleWorkspace(const Json::Value &workspaces,
uint8_t focused_workspace, bool prev) const {
auto inc = prev ? -1 : 1; auto inc = prev ? -1 : 1;
int size = workspaces_.size(); int size = workspaces.size();
uint8_t idx = 0; uint8_t idx = 0;
for (int i = focused_workspace; i < size && i >= 0; i += inc) { for (int i = focused_workspace; i < size && i >= 0; i += inc) {
bool same_output = (workspaces_[i]["output"].asString() == bar_.output->name && bool same_output = (workspaces[i]["output"].asString() == bar_.output->name &&
!config_["all-outputs"].asBool()) || !config_["all-outputs"].asBool()) ||
config_["all-outputs"].asBool(); config_["all-outputs"].asBool();
bool same_name = bool same_name =
workspaces_[i]["name"].asString() == workspaces_[focused_workspace]["name"].asString(); workspaces[i]["name"].asString() == workspaces[focused_workspace]["name"].asString();
if (same_output && !same_name) { if (same_output && !same_name) {
return workspaces_[i]["name"].asString(); return workspaces[i]["name"].asString();
} }
if (prev && i - 1 < 0) { if (prev && i - 1 < 0) {
i = size; i = size;
} else if (!prev && i + 1 >= size) { } else if (!prev && i + 1 >= size) {
i = -1; i = -1;
} else if (idx >= workspaces_.size()) { } else if (idx >= workspaces.size()) {
return ""; return "";
} }
idx += 1; idx += 1;
@ -227,9 +234,10 @@ const std::string Workspaces::getCycleWorkspace(uint8_t focused_workspace, bool
return ""; return "";
} }
uint16_t Workspaces::getWorkspaceIndex(const std::string &name) const { uint16_t Workspaces::getWorkspaceIndex(const Json::Value &workspaces,
const std::string &name) const {
uint16_t idx = 0; uint16_t idx = 0;
for (const auto &workspace : workspaces_) { for (const auto &workspace : workspaces) {
if (workspace["name"].asString() == name) { if (workspace["name"].asString() == name) {
return idx; return idx;
} }
@ -238,7 +246,7 @@ uint16_t Workspaces::getWorkspaceIndex(const std::string &name) const {
idx += 1; idx += 1;
} }
} }
return workspaces_.size(); return workspaces.size();
} }
std::string Workspaces::trimWorkspaceName(std::string name) { std::string Workspaces::trimWorkspaceName(std::string name) {