mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-11-04 01:32:42 +01:00 
			
		
		
		
	fix(Workspaces): fix concurrence and move json parser to ipc client
This commit is contained in:
		@@ -97,11 +97,15 @@ struct Ipc::ipc_response Ipc::recv(int fd) {
 | 
			
		||||
  while (total < data32[0]) {
 | 
			
		||||
    auto res = ::recv(fd, payload.data() + total, data32[0] - total, 0);
 | 
			
		||||
    if (res < 0) {
 | 
			
		||||
      if (errno == EINTR || errno == EAGAIN) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      throw std::runtime_error("Unable to receive IPC payload");
 | 
			
		||||
    }
 | 
			
		||||
    total += res;
 | 
			
		||||
  }
 | 
			
		||||
  return {data32[0], data32[1], &payload.front()};
 | 
			
		||||
  auto parsed = parser_.parse(&payload.front(), data32[0]);
 | 
			
		||||
  return {data32[0], data32[1], parsed};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Ipc::ipc_response Ipc::send(int fd, uint32_t type, const std::string& payload) {
 | 
			
		||||
@@ -130,7 +134,7 @@ void Ipc::sendCmd(uint32_t type, const std::string& payload) {
 | 
			
		||||
void Ipc::subscribe(const std::string& payload) {
 | 
			
		||||
  std::lock_guard<std::mutex> lock(mutex_event_);
 | 
			
		||||
  auto res = Ipc::send(fd_event_, IPC_SUBSCRIBE, payload);
 | 
			
		||||
  if (res.payload != "{\"success\": true}") {
 | 
			
		||||
  if (!res.payload["success"].asBool()) {
 | 
			
		||||
    throw std::runtime_error("Unable to subscribe ipc event");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -16,9 +16,8 @@ Mode::Mode(const std::string& id, const Bar& bar, const Json::Value& config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Mode::onEvent(const struct Ipc::ipc_response res) {
 | 
			
		||||
  auto parsed = parser_.parse(res.payload);
 | 
			
		||||
  if (parsed["change"] != "default") {
 | 
			
		||||
    mode_ = parsed["change"].asString();
 | 
			
		||||
  if (res.payload["change"] != "default") {
 | 
			
		||||
    mode_ = res.payload["change"].asString();
 | 
			
		||||
  } else {
 | 
			
		||||
    mode_.clear();
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,18 +21,17 @@ Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Window::onEvent(const struct Ipc::ipc_response res) {
 | 
			
		||||
  auto parsed = parser_.parse(res.payload);
 | 
			
		||||
  auto data = res.payload;
 | 
			
		||||
  // Check for waybar prevents flicker when hovering window module
 | 
			
		||||
  if ((parsed["change"] == "focus" || parsed["change"] == "title") &&
 | 
			
		||||
      parsed["container"]["focused"].asBool() &&
 | 
			
		||||
      parsed["container"]["name"].asString() != "waybar") {
 | 
			
		||||
    window_ = Glib::Markup::escape_text(parsed["container"]["name"].asString());
 | 
			
		||||
    windowId_ = parsed["container"]["id"].asInt();
 | 
			
		||||
  if ((data["change"] == "focus" || data["change"] == "title") &&
 | 
			
		||||
      data["container"]["focused"].asBool() && data["container"]["name"].asString() != "waybar") {
 | 
			
		||||
    window_ = Glib::Markup::escape_text(data["container"]["name"].asString());
 | 
			
		||||
    windowId_ = data["container"]["id"].asInt();
 | 
			
		||||
    dp.emit();
 | 
			
		||||
  } else if ((parsed["change"] == "close" && parsed["container"]["focused"].asBool() &&
 | 
			
		||||
              windowId_ == parsed["container"]["id"].asInt()) ||
 | 
			
		||||
             (parsed["change"] == "focus" && parsed["current"]["focus"].isArray() &&
 | 
			
		||||
              parsed["current"]["focus"].empty())) {
 | 
			
		||||
  } else if ((data["change"] == "close" && data["container"]["focused"].asBool() &&
 | 
			
		||||
              windowId_ == data["container"]["id"].asInt()) ||
 | 
			
		||||
             (data["change"] == "focus" && data["current"]["focus"].isArray() &&
 | 
			
		||||
              data["current"]["focus"].empty())) {
 | 
			
		||||
    window_.clear();
 | 
			
		||||
    windowId_ = -1;
 | 
			
		||||
    dp.emit();
 | 
			
		||||
@@ -40,8 +39,7 @@ void Window::onEvent(const struct Ipc::ipc_response res) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Window::onCmd(const struct Ipc::ipc_response res) {
 | 
			
		||||
  auto parsed = parser_.parse(res.payload);
 | 
			
		||||
  auto [id, name] = getFocusedNode(parsed["nodes"]);
 | 
			
		||||
  auto [id, name] = getFocusedNode(res.payload["nodes"]);
 | 
			
		||||
  windowId_ = id;
 | 
			
		||||
  window_ = name;
 | 
			
		||||
  dp.emit();
 | 
			
		||||
 
 | 
			
		||||
@@ -23,17 +23,19 @@ void Workspaces::onEvent(const struct Ipc::ipc_response res) { ipc_.sendCmd(IPC_
 | 
			
		||||
 | 
			
		||||
void Workspaces::onCmd(const struct Ipc::ipc_response res) {
 | 
			
		||||
  if (res.type == IPC_GET_WORKSPACES) {
 | 
			
		||||
    auto workspaces = parser_.parse(res.payload);
 | 
			
		||||
    workspaces_.clear();
 | 
			
		||||
    std::copy_if(workspaces.begin(),
 | 
			
		||||
                 workspaces.end(),
 | 
			
		||||
                 std::back_inserter(workspaces_),
 | 
			
		||||
                 [&](const auto &workspace) {
 | 
			
		||||
                   return !config_["all-outputs"].asBool()
 | 
			
		||||
                              ? workspace["output"].asString() == bar_.output->name
 | 
			
		||||
                              : true;
 | 
			
		||||
                 });
 | 
			
		||||
    dp.emit();
 | 
			
		||||
    if (res.payload.isArray()) {
 | 
			
		||||
      std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
      workspaces_.clear();
 | 
			
		||||
      std::copy_if(res.payload.begin(),
 | 
			
		||||
                   res.payload.end(),
 | 
			
		||||
                   std::back_inserter(workspaces_),
 | 
			
		||||
                   [&](const auto &workspace) {
 | 
			
		||||
                     return !config_["all-outputs"].asBool()
 | 
			
		||||
                                ? workspace["output"].asString() == bar_.output->name
 | 
			
		||||
                                : true;
 | 
			
		||||
                   });
 | 
			
		||||
      dp.emit();
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if (scrolling_) {
 | 
			
		||||
      scrolling_ = false;
 | 
			
		||||
@@ -69,7 +71,8 @@ bool Workspaces::filterButtons() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Workspaces::update() -> void {
 | 
			
		||||
  bool needReorder = filterButtons();
 | 
			
		||||
  std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
  bool                        needReorder = filterButtons();
 | 
			
		||||
  for (auto it = workspaces_.begin(); it != workspaces_.end(); ++it) {
 | 
			
		||||
    auto bit = buttons_.find((*it)["name"].asString());
 | 
			
		||||
    if (bit == buttons_.end()) {
 | 
			
		||||
@@ -149,39 +152,42 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
  if (scrolling_) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  scrolling_ = true;
 | 
			
		||||
  std::string name;
 | 
			
		||||
  auto        it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
 | 
			
		||||
    return workspace["focused"].asBool();
 | 
			
		||||
  });
 | 
			
		||||
  if (it == workspaces_.end()) {
 | 
			
		||||
    scrolling_ = false;
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  switch (e->direction) {
 | 
			
		||||
    case GDK_SCROLL_DOWN:
 | 
			
		||||
    case GDK_SCROLL_RIGHT:
 | 
			
		||||
      name = getCycleWorkspace(it, false);
 | 
			
		||||
      break;
 | 
			
		||||
    case GDK_SCROLL_UP:
 | 
			
		||||
    case GDK_SCROLL_LEFT:
 | 
			
		||||
      name = getCycleWorkspace(it, true);
 | 
			
		||||
      break;
 | 
			
		||||
    case GDK_SCROLL_SMOOTH:
 | 
			
		||||
      gdouble delta_x, delta_y;
 | 
			
		||||
      gdk_event_get_scroll_deltas(reinterpret_cast<const GdkEvent *>(e), &delta_x, &delta_y);
 | 
			
		||||
      if (delta_y < 0) {
 | 
			
		||||
        name = getCycleWorkspace(it, true);
 | 
			
		||||
      } else if (delta_y > 0) {
 | 
			
		||||
  scrolling_ = true;
 | 
			
		||||
  {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
    auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
 | 
			
		||||
      return workspace["focused"].asBool();
 | 
			
		||||
    });
 | 
			
		||||
    if (it == workspaces_.end()) {
 | 
			
		||||
      scrolling_ = false;
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    switch (e->direction) {
 | 
			
		||||
      case GDK_SCROLL_DOWN:
 | 
			
		||||
      case GDK_SCROLL_RIGHT:
 | 
			
		||||
        name = getCycleWorkspace(it, false);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  if (name.empty() || name == (*it)["name"].asString()) {
 | 
			
		||||
    scrolling_ = false;
 | 
			
		||||
    return false;
 | 
			
		||||
        break;
 | 
			
		||||
      case GDK_SCROLL_UP:
 | 
			
		||||
      case GDK_SCROLL_LEFT:
 | 
			
		||||
        name = getCycleWorkspace(it, true);
 | 
			
		||||
        break;
 | 
			
		||||
      case GDK_SCROLL_SMOOTH:
 | 
			
		||||
        gdouble delta_x, delta_y;
 | 
			
		||||
        gdk_event_get_scroll_deltas(reinterpret_cast<const GdkEvent *>(e), &delta_x, &delta_y);
 | 
			
		||||
        if (delta_y < 0) {
 | 
			
		||||
          name = getCycleWorkspace(it, true);
 | 
			
		||||
        } else if (delta_y > 0) {
 | 
			
		||||
          name = getCycleWorkspace(it, false);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    if (name.empty() || name == (*it)["name"].asString()) {
 | 
			
		||||
      scrolling_ = false;
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
 | 
			
		||||
  return true;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user