mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-11-04 09:42:42 +01:00 
			
		
		
		
	workspaces.cpp
This commit is contained in:
		@@ -28,6 +28,16 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
 | 
			
		||||
    icons_map_.emplace("", "");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto config_all_outputs = config_["all-outputs"];
 | 
			
		||||
  if (config_all_outputs.isBool()) {
 | 
			
		||||
    all_outputs_ = config_all_outputs.asBool();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto config_show_special = config_["show-special"];
 | 
			
		||||
  if (config_show_special.isBool()) {
 | 
			
		||||
    show_special_ = config_show_special.asBool();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  box_.set_name("workspaces");
 | 
			
		||||
  if (!id.empty()) {
 | 
			
		||||
    box_.get_style_context()->add_class(id);
 | 
			
		||||
@@ -43,10 +53,12 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
 | 
			
		||||
  gIPC->registerForIPC("workspace", this);
 | 
			
		||||
  gIPC->registerForIPC("createworkspace", this);
 | 
			
		||||
  gIPC->registerForIPC("destroyworkspace", this);
 | 
			
		||||
  gIPC->registerForIPC("focusedmon", this);
 | 
			
		||||
  gIPC->registerForIPC("moveworkspace", this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Workspaces::update() -> void {
 | 
			
		||||
  for (int &workspace_to_remove : workspaces_to_remove_) {
 | 
			
		||||
  for (std::string workspace_to_remove : workspaces_to_remove_) {
 | 
			
		||||
    remove_workspace(workspace_to_remove);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -56,19 +68,14 @@ auto Workspaces::update() -> void {
 | 
			
		||||
    create_workspace(workspace_to_create);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  workspaces_to_create_.clear();
 | 
			
		||||
 | 
			
		||||
  for (std::unique_ptr<Workspace> &workspace : workspaces_) {
 | 
			
		||||
    workspace->set_active(workspace->id() == active_workspace_id);
 | 
			
		||||
 | 
			
		||||
  for (auto &workspace : workspaces_) {
 | 
			
		||||
    workspace->set_active(workspace->name() == active_workspace_name);
 | 
			
		||||
    std::string &workspace_icon = icons_map_[""];
 | 
			
		||||
    if (with_icon_) {
 | 
			
		||||
      workspace_icon = workspace->select_icon(icons_map_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    workspace->update(format_, workspace_icon);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  AModule::update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -76,35 +83,58 @@ void Workspaces::onEvent(const std::string &ev) {
 | 
			
		||||
  std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
  std::string eventName(begin(ev), begin(ev) + ev.find_first_of('>'));
 | 
			
		||||
  std::string payload = ev.substr(eventName.size() + 2);
 | 
			
		||||
 | 
			
		||||
  if (eventName == "workspace") {
 | 
			
		||||
    std::from_chars(payload.data(), payload.data() + payload.size(), active_workspace_id);
 | 
			
		||||
    active_workspace_name = payload;
 | 
			
		||||
 | 
			
		||||
  } else if (eventName == "destroyworkspace") {
 | 
			
		||||
    int deleted_workspace_id;
 | 
			
		||||
    std::from_chars(payload.data(), payload.data() + payload.size(), deleted_workspace_id);
 | 
			
		||||
    workspaces_to_remove_.push_back(deleted_workspace_id);
 | 
			
		||||
    workspaces_to_remove_.push_back(payload);
 | 
			
		||||
 | 
			
		||||
  } else if (eventName == "createworkspace") {
 | 
			
		||||
    int new_workspace_id;
 | 
			
		||||
    std::from_chars(payload.data(), payload.data() + payload.size(), new_workspace_id);
 | 
			
		||||
    workspaces_to_create_.push_back(new_workspace_id);
 | 
			
		||||
    const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces");
 | 
			
		||||
    for (auto &workspace_json : workspaces_json) {
 | 
			
		||||
      if (workspace_json["name"].asString() == payload &&
 | 
			
		||||
          (all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) &&
 | 
			
		||||
          (workspace_json["name"].asString().find("special:") != 0 || show_special()))
 | 
			
		||||
        create_workspace(workspace_json);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  } else if (eventName == "focusedmon") {
 | 
			
		||||
    active_workspace_name = payload.substr(payload.find(",") + 1);
 | 
			
		||||
 | 
			
		||||
  } else if (eventName == "moveworkspace") {
 | 
			
		||||
    std::string workspace = payload.substr(0, payload.find(","));
 | 
			
		||||
    std::string new_monitor = payload.substr(payload.find(",") + 1);
 | 
			
		||||
    if (all_outputs()) {
 | 
			
		||||
      if (bar_.output->name == new_monitor) {  // TODO: implement this better
 | 
			
		||||
        const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces");
 | 
			
		||||
        for (auto &workspace_json : workspaces_json) {
 | 
			
		||||
          if (workspace_json["name"].asString() == workspace &&
 | 
			
		||||
              bar_.output->name == workspace_json["monitor"].asString())
 | 
			
		||||
            create_workspace(workspace_json);
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        workspaces_to_remove_.push_back(workspace);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  dp.emit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspaces::create_workspace(int id) {
 | 
			
		||||
  workspaces_.push_back(std::make_unique<Workspace>(id));
 | 
			
		||||
void Workspaces::create_workspace(const Json::Value &value) {
 | 
			
		||||
  workspaces_.push_back(std::make_unique<Workspace>(value));
 | 
			
		||||
  Gtk::Button &new_workspace_button = workspaces_.back()->button();
 | 
			
		||||
  box_.pack_start(new_workspace_button, false, false);
 | 
			
		||||
  sort_workspaces();
 | 
			
		||||
  new_workspace_button.show_all();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspaces::remove_workspace(int id) {
 | 
			
		||||
void Workspaces::remove_workspace(std::string name) {
 | 
			
		||||
  auto workspace = std::find_if(workspaces_.begin(), workspaces_.end(),
 | 
			
		||||
                                [&](std::unique_ptr<Workspace> &x) { return x->id() == id; });
 | 
			
		||||
                                [&](std::unique_ptr<Workspace> &x) { return x->name() == name; });
 | 
			
		||||
 | 
			
		||||
  if (workspace == workspaces_.end()) {
 | 
			
		||||
    spdlog::warn("Can't find workspace with id {}", id);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -113,16 +143,13 @@ void Workspaces::remove_workspace(int id) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspaces::init() {
 | 
			
		||||
  const auto activeWorkspace = WorkspaceDto::parse(gIPC->getSocket1JsonReply("activeworkspace"));
 | 
			
		||||
  active_workspace_id = activeWorkspace.id;
 | 
			
		||||
  active_workspace_name = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString();
 | 
			
		||||
 | 
			
		||||
  const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces");
 | 
			
		||||
  for (const Json::Value &workspace_json : workspaces_json) {
 | 
			
		||||
    workspaces_.push_back(
 | 
			
		||||
        std::make_unique<Workspace>(Workspace(WorkspaceDto::parse(workspace_json))));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (auto &workspace : workspaces_) {
 | 
			
		||||
    box_.pack_start(workspace->button(), false, false);
 | 
			
		||||
    if ((all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) &&
 | 
			
		||||
        (workspace_json["name"].asString().find("special") != 0 || show_special()))
 | 
			
		||||
      create_workspace(workspace_json);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  sort_workspaces();
 | 
			
		||||
@@ -136,13 +163,27 @@ Workspaces::~Workspaces() {
 | 
			
		||||
  std::lock_guard<std::mutex> lg(mutex_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WorkspaceDto WorkspaceDto::parse(const Json::Value &value) {
 | 
			
		||||
  return WorkspaceDto{value["id"].asInt()};
 | 
			
		||||
Workspace::Workspace(const Json::Value &value) {
 | 
			
		||||
  id_ = value["id"].asInt();
 | 
			
		||||
  name_ = value["name"].asString();
 | 
			
		||||
  monitor_ = value["monitor"].asString();  // TODO:allow using monitor desc
 | 
			
		||||
  windows_ = value["id"].asInt();
 | 
			
		||||
  active_ = 1;
 | 
			
		||||
  is_special_ = 0;
 | 
			
		||||
 | 
			
		||||
  if (name_.find("name:") == 0) {
 | 
			
		||||
    name_ = name_.substr(5);
 | 
			
		||||
  } else if (name_.find("special") == 0) {
 | 
			
		||||
    name_ = id_ == -99 ? name_ : name_.substr(13);
 | 
			
		||||
    is_special_ = 1;
 | 
			
		||||
  }
 | 
			
		||||
  // spdlog::info("\nNew workspace:\n\tid:({})\n\tname:({})\n\tmonitor:({})\n\tspecial:({})\n", id_,
 | 
			
		||||
  // name_, monitor_, is_special_ ? "yes" : "no"); //make less noisy
 | 
			
		||||
 | 
			
		||||
Workspace::Workspace(WorkspaceDto dto) : Workspace(dto.id){};
 | 
			
		||||
  button_.add_events(Gdk::BUTTON_PRESS_MASK);
 | 
			
		||||
  button_.signal_button_press_event().connect(sigc::mem_fun(*this, &Workspace::handle_clicked),
 | 
			
		||||
                                              false);
 | 
			
		||||
 | 
			
		||||
Workspace::Workspace(int id) : id_(id) {
 | 
			
		||||
  button_.set_relief(Gtk::RELIEF_NONE);
 | 
			
		||||
  content_.set_center_widget(label_);
 | 
			
		||||
  button_.add(content_);
 | 
			
		||||
@@ -161,14 +202,29 @@ void Workspace::update(const std::string &format, const std::string &icon) {
 | 
			
		||||
  Glib::RefPtr<Gtk::StyleContext> style_context = button_.get_style_context();
 | 
			
		||||
  add_or_remove_class(style_context, active(), "active");
 | 
			
		||||
 | 
			
		||||
  label_.set_markup(
 | 
			
		||||
      fmt::format(fmt::runtime(format), fmt::arg("id", id()), fmt::arg("icon", icon)));
 | 
			
		||||
  label_.set_markup(fmt::format(fmt::runtime(format), fmt::arg("id", id()),
 | 
			
		||||
                                fmt::arg("name", name()), fmt::arg("icon", icon)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Workspaces::sort_workspaces() {
 | 
			
		||||
  std::sort(workspaces_.begin(), workspaces_.end(),
 | 
			
		||||
            [](std::unique_ptr<Workspace> &lhs, std::unique_ptr<Workspace> &rhs) {
 | 
			
		||||
              return lhs->id() < rhs->id();
 | 
			
		||||
            [](std::unique_ptr<Workspace> &a, std::unique_ptr<Workspace> &b) {
 | 
			
		||||
              // normal -> named -> special -> named special
 | 
			
		||||
              if (a->id() > 0 && b->id() > 0) {
 | 
			
		||||
                return a->id() < b->id();
 | 
			
		||||
              }
 | 
			
		||||
              if (a->id() < 0 && b->id() < 0) {
 | 
			
		||||
                if ((a->is_special()) ^ (a->is_special())) {
 | 
			
		||||
                  return a->id() > b->id();
 | 
			
		||||
                } else {
 | 
			
		||||
                  return a->id() < b->id();
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              if ((a->id() > 0) ^ (b->id() > 0)) {
 | 
			
		||||
                return a->id() > b->id();
 | 
			
		||||
              }
 | 
			
		||||
              spdlog::error("huh!!?");
 | 
			
		||||
              return false;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
  for (size_t i = 0; i < workspaces_.size(); ++i) {
 | 
			
		||||
@@ -193,7 +249,20 @@ std::string &Workspace::select_icon(std::map<std::string, std::string> &icons_ma
 | 
			
		||||
  if (default_icon_it != icons_map.end()) {
 | 
			
		||||
    return default_icon_it->second;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return icons_map[""];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Workspace::handle_clicked(GdkEventButton *bt) -> bool {
 | 
			
		||||
  if (id() > 0) {  // normal
 | 
			
		||||
    system(("hyprctl dispatch workspace " + std::to_string(id()) + " &> /dev/null").c_str());
 | 
			
		||||
  } else if (!is_special()) {  // named normal
 | 
			
		||||
    system(("hyprctl dispatch workspace name:" + name() + " &> /dev/null").c_str());
 | 
			
		||||
  } else if (id() != -99) {  // named special
 | 
			
		||||
    system(("hyprctl dispatch togglespecialworkspace name:" + name() + " &> /dev/null").c_str());
 | 
			
		||||
  } else {  // special
 | 
			
		||||
    system("hyprctl dispatch togglespecialworkspace special &> /dev/null");
 | 
			
		||||
  }
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace waybar::modules::hyprland
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user