mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-11-04 09:42:42 +01:00 
			
		
		
		
	Merge branch 'master' into master
This commit is contained in:
		@@ -93,8 +93,8 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &
 | 
			
		||||
  {
 | 
			
		||||
    std::unique_ptr<udev, UdevDeleter> udev_check{udev_new()};
 | 
			
		||||
    check_nn(udev_check.get(), "Udev check new failed");
 | 
			
		||||
    enumerate_devices(
 | 
			
		||||
        devices_.begin(), devices_.end(), std::back_inserter(devices_), udev_check.get());
 | 
			
		||||
    enumerate_devices(devices_.begin(), devices_.end(), std::back_inserter(devices_),
 | 
			
		||||
                      udev_check.get());
 | 
			
		||||
    if (devices_.empty()) {
 | 
			
		||||
      throw std::runtime_error("No backlight found");
 | 
			
		||||
    }
 | 
			
		||||
@@ -108,8 +108,7 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &
 | 
			
		||||
    std::unique_ptr<udev_monitor, UdevMonitorDeleter> mon{
 | 
			
		||||
        udev_monitor_new_from_netlink(udev.get(), "udev")};
 | 
			
		||||
    check_nn(mon.get(), "udev monitor new failed");
 | 
			
		||||
    check_gte(udev_monitor_filter_add_match_subsystem_devtype(mon.get(), "backlight", nullptr),
 | 
			
		||||
              0,
 | 
			
		||||
    check_gte(udev_monitor_filter_add_match_subsystem_devtype(mon.get(), "backlight", nullptr), 0,
 | 
			
		||||
              "udev failed to add monitor filter: ");
 | 
			
		||||
    udev_monitor_enable_receiving(mon.get());
 | 
			
		||||
 | 
			
		||||
@@ -126,8 +125,8 @@ waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &
 | 
			
		||||
    epoll_event events[EPOLL_MAX_EVENTS];
 | 
			
		||||
 | 
			
		||||
    while (udev_thread_.isRunning()) {
 | 
			
		||||
      const int event_count = epoll_wait(
 | 
			
		||||
          epoll_fd.get(), events, EPOLL_MAX_EVENTS, std::chrono::milliseconds{interval_}.count());
 | 
			
		||||
      const int event_count = epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS,
 | 
			
		||||
                                         std::chrono::milliseconds{interval_}.count());
 | 
			
		||||
      if (!udev_thread_.isRunning()) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
@@ -173,9 +172,10 @@ auto waybar::modules::Backlight::update() -> void {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const uint8_t percent = best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
 | 
			
		||||
    label_.set_markup(fmt::format(
 | 
			
		||||
        format_, fmt::arg("percent", std::to_string(percent)), fmt::arg("icon", getIcon(percent))));
 | 
			
		||||
    const uint8_t percent =
 | 
			
		||||
        best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
 | 
			
		||||
    label_.set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)),
 | 
			
		||||
                                  fmt::arg("icon", getIcon(percent))));
 | 
			
		||||
    getState(percent);
 | 
			
		||||
  } else {
 | 
			
		||||
    if (!previous_best_.has_value()) {
 | 
			
		||||
@@ -241,7 +241,7 @@ void waybar::modules::Backlight::enumerate_devices(ForwardIt first, ForwardIt la
 | 
			
		||||
  udev_list_entry *enum_devices = udev_enumerate_get_list_entry(enumerate.get());
 | 
			
		||||
  udev_list_entry *dev_list_entry;
 | 
			
		||||
  udev_list_entry_foreach(dev_list_entry, enum_devices) {
 | 
			
		||||
    const char *                                    path = udev_list_entry_get_name(dev_list_entry);
 | 
			
		||||
    const char *path = udev_list_entry_get_name(dev_list_entry);
 | 
			
		||||
    std::unique_ptr<udev_device, UdevDeviceDeleter> dev{udev_device_new_from_syspath(udev, path)};
 | 
			
		||||
    check_nn(dev.get(), "dev new failed");
 | 
			
		||||
    upsert_device(first, last, inserter, dev.get());
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ void waybar::modules::Battery::worker() {
 | 
			
		||||
  };
 | 
			
		||||
  thread_ = [this] {
 | 
			
		||||
    struct inotify_event event = {0};
 | 
			
		||||
    int                  nbytes = read(battery_watch_fd_, &event, sizeof(event));
 | 
			
		||||
    int nbytes = read(battery_watch_fd_, &event, sizeof(event));
 | 
			
		||||
    if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
 | 
			
		||||
      thread_.stop();
 | 
			
		||||
      return;
 | 
			
		||||
@@ -61,7 +61,7 @@ void waybar::modules::Battery::worker() {
 | 
			
		||||
  };
 | 
			
		||||
  thread_battery_update_ = [this] {
 | 
			
		||||
    struct inotify_event event = {0};
 | 
			
		||||
    int                  nbytes = read(global_watch_fd_, &event, sizeof(event));
 | 
			
		||||
    int nbytes = read(global_watch_fd_, &event, sizeof(event));
 | 
			
		||||
    if (nbytes != sizeof(event) || event.mask & IN_IGNORED) {
 | 
			
		||||
      thread_.stop();
 | 
			
		||||
      return;
 | 
			
		||||
@@ -94,7 +94,7 @@ void waybar::modules::Battery::refreshBatteries() {
 | 
			
		||||
        std::string type;
 | 
			
		||||
        std::ifstream(node.path() / "type") >> type;
 | 
			
		||||
 | 
			
		||||
        if (!type.compare("Battery")){
 | 
			
		||||
        if (!type.compare("Battery")) {
 | 
			
		||||
          check_map[node.path()] = true;
 | 
			
		||||
          auto search = batteries_.find(node.path());
 | 
			
		||||
          if (search == batteries_.end()) {
 | 
			
		||||
@@ -139,11 +139,16 @@ void waybar::modules::Battery::refreshBatteries() {
 | 
			
		||||
 | 
			
		||||
// Unknown > Full > Not charging > Discharging > Charging
 | 
			
		||||
static bool status_gt(const std::string& a, const std::string& b) {
 | 
			
		||||
  if (a == b) return false;
 | 
			
		||||
  else if (a == "Unknown") return true;
 | 
			
		||||
  else if (a == "Full" && b != "Unknown") return true;
 | 
			
		||||
  else if (a == "Not charging" && b != "Unknown" && b != "Full") return true;
 | 
			
		||||
  else if (a == "Discharging" && b != "Unknown" && b != "Full" && b != "Not charging") return true;
 | 
			
		||||
  if (a == b)
 | 
			
		||||
    return false;
 | 
			
		||||
  else if (a == "Unknown")
 | 
			
		||||
    return true;
 | 
			
		||||
  else if (a == "Full" && b != "Unknown")
 | 
			
		||||
    return true;
 | 
			
		||||
  else if (a == "Not charging" && b != "Unknown" && b != "Full")
 | 
			
		||||
    return true;
 | 
			
		||||
  else if (a == "Discharging" && b != "Unknown" && b != "Full" && b != "Not charging")
 | 
			
		||||
    return true;
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -151,19 +156,19 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
 | 
			
		||||
  std::lock_guard<std::mutex> guard(battery_list_mutex_);
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    uint32_t    total_power = 0;   // μW
 | 
			
		||||
    uint32_t    total_energy = 0;  // μWh
 | 
			
		||||
    uint32_t    total_energy_full = 0;
 | 
			
		||||
    uint32_t    total_energy_full_design = 0;
 | 
			
		||||
    uint32_t    total_capacity{0};
 | 
			
		||||
    uint32_t total_power = 0;   // μW
 | 
			
		||||
    uint32_t total_energy = 0;  // μWh
 | 
			
		||||
    uint32_t total_energy_full = 0;
 | 
			
		||||
    uint32_t total_energy_full_design = 0;
 | 
			
		||||
    uint32_t total_capacity{0};
 | 
			
		||||
    std::string status = "Unknown";
 | 
			
		||||
    for (auto const& item : batteries_) {
 | 
			
		||||
      auto bat = item.first;
 | 
			
		||||
      uint32_t    power_now;
 | 
			
		||||
      uint32_t    energy_full;
 | 
			
		||||
      uint32_t    energy_now;
 | 
			
		||||
      uint32_t    energy_full_design;
 | 
			
		||||
      uint32_t    capacity{0};
 | 
			
		||||
      uint32_t power_now;
 | 
			
		||||
      uint32_t energy_full;
 | 
			
		||||
      uint32_t energy_now;
 | 
			
		||||
      uint32_t energy_full_design;
 | 
			
		||||
      uint32_t capacity{0};
 | 
			
		||||
      std::string _status;
 | 
			
		||||
      std::getline(std::ifstream(bat / "status"), _status);
 | 
			
		||||
 | 
			
		||||
@@ -198,17 +203,17 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
 | 
			
		||||
        energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000;
 | 
			
		||||
        energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000;
 | 
			
		||||
        energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000;
 | 
			
		||||
      } // Gamepads such as PS Dualshock provide the only capacity
 | 
			
		||||
        else if (fs::exists(bat / "energy_now") && fs::exists(bat / "energy_full")) {
 | 
			
		||||
          std::ifstream(bat / "power_now") >> power_now;
 | 
			
		||||
          std::ifstream(bat / "energy_now") >> energy_now;
 | 
			
		||||
          std::ifstream(bat / "energy_full") >> energy_full;
 | 
			
		||||
          std::ifstream(bat / "energy_full_design") >> energy_full_design;
 | 
			
		||||
      }  // Gamepads such as PS Dualshock provide the only capacity
 | 
			
		||||
      else if (fs::exists(bat / "energy_now") && fs::exists(bat / "energy_full")) {
 | 
			
		||||
        std::ifstream(bat / "power_now") >> power_now;
 | 
			
		||||
        std::ifstream(bat / "energy_now") >> energy_now;
 | 
			
		||||
        std::ifstream(bat / "energy_full") >> energy_full;
 | 
			
		||||
        std::ifstream(bat / "energy_full_design") >> energy_full_design;
 | 
			
		||||
      } else {
 | 
			
		||||
        std::ifstream(bat / "capacity") >> capacity;
 | 
			
		||||
        power_now          = 0;
 | 
			
		||||
        energy_now         = 0;
 | 
			
		||||
        energy_full        = 0;
 | 
			
		||||
        power_now = 0;
 | 
			
		||||
        energy_now = 0;
 | 
			
		||||
        energy_full = 0;
 | 
			
		||||
        energy_full_design = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -241,14 +246,14 @@ const std::tuple<uint8_t, float, std::string, float> waybar::modules::Battery::g
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    float capacity{0.0f};
 | 
			
		||||
    if(total_energy_full > 0.0f) {
 | 
			
		||||
      capacity = ((float)total_energy * 100.0f / (float) total_energy_full);
 | 
			
		||||
    if (total_energy_full > 0.0f) {
 | 
			
		||||
      capacity = ((float)total_energy * 100.0f / (float)total_energy_full);
 | 
			
		||||
    } else {
 | 
			
		||||
      capacity = (float)total_capacity;
 | 
			
		||||
    }
 | 
			
		||||
    // Handle design-capacity
 | 
			
		||||
    if (config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) {
 | 
			
		||||
        capacity = ((float)total_energy * 100.0f / (float) total_energy_full_design);
 | 
			
		||||
      capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design);
 | 
			
		||||
    }
 | 
			
		||||
    // Handle full-at
 | 
			
		||||
    if (config_["full-at"].isUInt()) {
 | 
			
		||||
@@ -295,7 +300,7 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai
 | 
			
		||||
  hoursRemaining = std::fabs(hoursRemaining);
 | 
			
		||||
  uint16_t full_hours = static_cast<uint16_t>(hoursRemaining);
 | 
			
		||||
  uint16_t minutes = static_cast<uint16_t>(60 * (hoursRemaining - full_hours));
 | 
			
		||||
  auto     format = std::string("{H} h {M} min");
 | 
			
		||||
  auto format = std::string("{H} h {M} min");
 | 
			
		||||
  if (full_hours == 0 && minutes == 0) {
 | 
			
		||||
    // Migh as well not show "0h 0min"
 | 
			
		||||
    return "";
 | 
			
		||||
@@ -317,9 +322,8 @@ auto waybar::modules::Battery::update() -> void {
 | 
			
		||||
  }
 | 
			
		||||
  auto status_pretty = status;
 | 
			
		||||
  // Transform to lowercase  and replace space with dash
 | 
			
		||||
  std::transform(status.begin(), status.end(), status.begin(), [](char ch) {
 | 
			
		||||
    return ch == ' ' ? '-' : std::tolower(ch);
 | 
			
		||||
  });
 | 
			
		||||
  std::transform(status.begin(), status.end(), status.begin(),
 | 
			
		||||
                 [](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
 | 
			
		||||
  auto format = format_;
 | 
			
		||||
  auto state = getState(capacity, true);
 | 
			
		||||
  auto time_remaining_formatted = formatTimeRemaining(time_remaining);
 | 
			
		||||
@@ -341,8 +345,7 @@ auto waybar::modules::Battery::update() -> void {
 | 
			
		||||
    } else if (config_["tooltip-format"].isString()) {
 | 
			
		||||
      tooltip_format = config_["tooltip-format"].asString();
 | 
			
		||||
    }
 | 
			
		||||
    label_.set_tooltip_text(fmt::format(tooltip_format,
 | 
			
		||||
                                        fmt::arg("timeTo", tooltip_text_default),
 | 
			
		||||
    label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default),
 | 
			
		||||
                                        fmt::arg("capacity", capacity),
 | 
			
		||||
                                        fmt::arg("time", time_remaining_formatted)));
 | 
			
		||||
  }
 | 
			
		||||
@@ -363,9 +366,7 @@ auto waybar::modules::Battery::update() -> void {
 | 
			
		||||
  } else {
 | 
			
		||||
    event_box_.show();
 | 
			
		||||
    auto icons = std::vector<std::string>{status + "-" + state, status, state};
 | 
			
		||||
    label_.set_markup(fmt::format(format,
 | 
			
		||||
                                  fmt::arg("capacity", capacity),
 | 
			
		||||
                                  fmt::arg("power", power),
 | 
			
		||||
    label_.set_markup(fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("power", power),
 | 
			
		||||
                                  fmt::arg("icon", getIcon(capacity, icons)),
 | 
			
		||||
                                  fmt::arg("time", time_remaining_formatted)));
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,44 +25,38 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
 | 
			
		||||
    : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true),
 | 
			
		||||
      current_time_zone_idx_(0),
 | 
			
		||||
      is_calendar_in_tooltip_(false),
 | 
			
		||||
      is_timezoned_list_in_tooltip_(false)
 | 
			
		||||
{
 | 
			
		||||
      is_timezoned_list_in_tooltip_(false) {
 | 
			
		||||
  if (config_["timezones"].isArray() && !config_["timezones"].empty()) {
 | 
			
		||||
    for (const auto& zone_name: config_["timezones"]) {
 | 
			
		||||
    for (const auto& zone_name : config_["timezones"]) {
 | 
			
		||||
      if (!zone_name.isString() || zone_name.asString().empty()) {
 | 
			
		||||
        time_zones_.push_back(nullptr);
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      time_zones_.push_back(
 | 
			
		||||
        date::locate_zone(
 | 
			
		||||
          zone_name.asString()
 | 
			
		||||
        )
 | 
			
		||||
      );
 | 
			
		||||
      time_zones_.push_back(date::locate_zone(zone_name.asString()));
 | 
			
		||||
    }
 | 
			
		||||
  } else if (config_["timezone"].isString() && !config_["timezone"].asString().empty()) {
 | 
			
		||||
    time_zones_.push_back(
 | 
			
		||||
        date::locate_zone(
 | 
			
		||||
          config_["timezone"].asString()
 | 
			
		||||
        )
 | 
			
		||||
      );
 | 
			
		||||
    time_zones_.push_back(date::locate_zone(config_["timezone"].asString()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If all timezones are parsed and no one is good, add nullptr to the timezones vector, to mark that local time should be shown.
 | 
			
		||||
  // If all timezones are parsed and no one is good, add nullptr to the timezones vector, to mark
 | 
			
		||||
  // that local time should be shown.
 | 
			
		||||
  if (!time_zones_.size()) {
 | 
			
		||||
    time_zones_.push_back(nullptr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!is_timezone_fixed()) {
 | 
			
		||||
    spdlog::warn("As using a timezone, some format args may be missing as the date library haven't got a release since 2018.");
 | 
			
		||||
    spdlog::warn(
 | 
			
		||||
        "As using a timezone, some format args may be missing as the date library haven't got a "
 | 
			
		||||
        "release since 2018.");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Check if a particular placeholder is present in the tooltip format, to know what to calculate on update.
 | 
			
		||||
  // Check if a particular placeholder is present in the tooltip format, to know what to calculate
 | 
			
		||||
  // on update.
 | 
			
		||||
  if (config_["tooltip-format"].isString()) {
 | 
			
		||||
    std::string trimmed_format = config_["tooltip-format"].asString();
 | 
			
		||||
    trimmed_format.erase(std::remove_if(trimmed_format.begin(),
 | 
			
		||||
                              trimmed_format.end(),
 | 
			
		||||
                              [](unsigned char x){return std::isspace(x);}),
 | 
			
		||||
               trimmed_format.end());
 | 
			
		||||
    trimmed_format.erase(std::remove_if(trimmed_format.begin(), trimmed_format.end(),
 | 
			
		||||
                                        [](unsigned char x) { return std::isspace(x); }),
 | 
			
		||||
                         trimmed_format.end());
 | 
			
		||||
    if (trimmed_format.find("{" + kCalendarPlaceholder + "}") != std::string::npos) {
 | 
			
		||||
      is_calendar_in_tooltip_ = true;
 | 
			
		||||
    }
 | 
			
		||||
@@ -87,7 +81,8 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const date::time_zone* waybar::modules::Clock::current_timezone() {
 | 
			
		||||
  return time_zones_[current_time_zone_idx_] ? time_zones_[current_time_zone_idx_] : date::current_zone();
 | 
			
		||||
  return time_zones_[current_time_zone_idx_] ? time_zones_[current_time_zone_idx_]
 | 
			
		||||
                                             : date::current_zone();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool waybar::modules::Clock::is_timezone_fixed() {
 | 
			
		||||
@@ -121,7 +116,9 @@ auto waybar::modules::Clock::update() -> void {
 | 
			
		||||
        timezoned_time_lines = timezones_text(&now);
 | 
			
		||||
      }
 | 
			
		||||
      auto tooltip_format = config_["tooltip-format"].asString();
 | 
			
		||||
      text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines), fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines));
 | 
			
		||||
      text =
 | 
			
		||||
          fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines),
 | 
			
		||||
                      fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines));
 | 
			
		||||
      label_.set_tooltip_markup(text);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -130,7 +127,7 @@ auto waybar::modules::Clock::update() -> void {
 | 
			
		||||
  ALabel::update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
bool waybar::modules::Clock::handleScroll(GdkEventScroll* e) {
 | 
			
		||||
  // defer to user commands if set
 | 
			
		||||
  if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
 | 
			
		||||
    return AModule::handleScroll(e);
 | 
			
		||||
@@ -149,7 +146,8 @@ bool waybar::modules::Clock::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
    size_t new_idx = current_time_zone_idx_ + 1;
 | 
			
		||||
    current_time_zone_idx_ = new_idx == nr_zones ? 0 : new_idx;
 | 
			
		||||
  } else {
 | 
			
		||||
    current_time_zone_idx_ = current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
 | 
			
		||||
    current_time_zone_idx_ =
 | 
			
		||||
        current_time_zone_idx_ == 0 ? nr_zones - 1 : current_time_zone_idx_ - 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  update();
 | 
			
		||||
@@ -164,14 +162,15 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const date::year_month ym(ymd.year(), ymd.month());
 | 
			
		||||
  const auto             curr_day = ymd.day();
 | 
			
		||||
  const auto curr_day = ymd.day();
 | 
			
		||||
 | 
			
		||||
  std::stringstream os;
 | 
			
		||||
  const auto        first_dow = first_day_of_week();
 | 
			
		||||
 | 
			
		||||
  const auto first_dow = first_day_of_week();
 | 
			
		||||
  int ws{0};    // weeks-pos: side(1 - left, 2 - right)
 | 
			
		||||
  int wn{0};    // weeknumber
 | 
			
		||||
  if (config_["calendar-weeks-pos"].isString()) {
 | 
			
		||||
    wn = (date::sys_days{date::year_month_day{ym / 1}} - date::sys_days{date::year_month_day{ymd.year() / 1 / 1}}).count() / 7 + 1;
 | 
			
		||||
    wn = (date::sys_days{date::year_month_day{ym/1}} - date::sys_days{date::year_month_day{ymd.year()/1/1}}).count()/7+1;
 | 
			
		||||
    if (config_["calendar-weeks-pos"].asString() == "left") {
 | 
			
		||||
      ws = 1;
 | 
			
		||||
      // Add paddings before the header
 | 
			
		||||
@@ -180,6 +179,7 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str
 | 
			
		||||
      ws = 2;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  weekdays_header(first_dow, os);
 | 
			
		||||
  /* Print weeknumber on the left for the first row*/
 | 
			
		||||
  if (ws == 1) {
 | 
			
		||||
@@ -246,7 +246,7 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std
 | 
			
		||||
    auto clen = ustring_clen(wd_ustring);
 | 
			
		||||
    auto wd_len = wd_ustring.length();
 | 
			
		||||
    while (clen > 2) {
 | 
			
		||||
      wd_ustring = wd_ustring.substr(0, wd_len-1);
 | 
			
		||||
      wd_ustring = wd_ustring.substr(0, wd_len - 1);
 | 
			
		||||
      wd_len--;
 | 
			
		||||
      clen = ustring_clen(wd_ustring);
 | 
			
		||||
    }
 | 
			
		||||
@@ -260,7 +260,8 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std
 | 
			
		||||
  } else os << res.str();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_point *now) -> std::string {
 | 
			
		||||
auto waybar::modules::Clock::timezones_text(std::chrono::system_clock::time_point* now)
 | 
			
		||||
    -> std::string {
 | 
			
		||||
  if (time_zones_.size() == 1) {
 | 
			
		||||
    return "";
 | 
			
		||||
  }
 | 
			
		||||
@@ -305,9 +306,9 @@ auto waybar::modules::Clock::first_day_of_week() -> date::weekday {
 | 
			
		||||
      newlocale(LC_ALL, locale_.name().c_str(), nullptr)};
 | 
			
		||||
  if (posix_locale) {
 | 
			
		||||
    const int i = (std::intptr_t)nl_langinfo_l(_NL_TIME_WEEK_1STDAY, posix_locale.get());
 | 
			
		||||
    auto      ymd = date::year(i / 10000) / (i / 100 % 100) / (i % 100);
 | 
			
		||||
    auto      wd = date::weekday(ymd);
 | 
			
		||||
    uint8_t   j = *nl_langinfo_l(_NL_TIME_FIRST_WEEKDAY, posix_locale.get());
 | 
			
		||||
    auto ymd = date::year(i / 10000) / (i / 100 % 100) / (i % 100);
 | 
			
		||||
    auto wd = date::weekday(ymd);
 | 
			
		||||
    uint8_t j = *nl_langinfo_l(_NL_TIME_FIRST_WEEKDAY, posix_locale.get());
 | 
			
		||||
    return wd + date::days(j - 1);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,19 @@
 | 
			
		||||
#include "modules/cpu.hpp"
 | 
			
		||||
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
// clang-format off
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <cstdlib>            // malloc
 | 
			
		||||
#include <unistd.h>           // sysconf
 | 
			
		||||
#include <cmath>              // NAN
 | 
			
		||||
// clang-format on
 | 
			
		||||
#include <unistd.h>  // sysconf
 | 
			
		||||
 | 
			
		||||
#include <cmath>    // NAN
 | 
			
		||||
#include <cstdlib>  // malloc
 | 
			
		||||
 | 
			
		||||
#include "modules/cpu.hpp"
 | 
			
		||||
 | 
			
		||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
 | 
			
		||||
#  include <sys/sched.h>
 | 
			
		||||
#include <sys/sched.h>
 | 
			
		||||
#else
 | 
			
		||||
#  include <sys/resource.h>
 | 
			
		||||
#include <sys/resource.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__NetBSD__)
 | 
			
		||||
@@ -32,26 +35,26 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
 | 
			
		||||
  pcp_time_t *cp_time = static_cast<pcp_time_t *>(malloc(sz)), *pcp_time = cp_time;
 | 
			
		||||
#if defined(__NetBSD__)
 | 
			
		||||
  int mib[] = {
 | 
			
		||||
    CTL_KERN,
 | 
			
		||||
    KERN_CP_TIME,
 | 
			
		||||
      CTL_KERN,
 | 
			
		||||
      KERN_CP_TIME,
 | 
			
		||||
  };
 | 
			
		||||
  if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
 | 
			
		||||
  if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
 | 
			
		||||
    throw std::runtime_error("sysctl kern.cp_time failed");
 | 
			
		||||
  }
 | 
			
		||||
  for (int state = 0; state < CPUSTATES; state++) {
 | 
			
		||||
    cp_time[state] = sum_cp_time[state];
 | 
			
		||||
  }
 | 
			
		||||
  pcp_time += CPUSTATES;
 | 
			
		||||
  if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
 | 
			
		||||
  if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
 | 
			
		||||
    throw std::runtime_error("sysctl kern.cp_time failed");
 | 
			
		||||
  }
 | 
			
		||||
#elif defined(__OpenBSD__)
 | 
			
		||||
  {
 | 
			
		||||
    int mib[] = {
 | 
			
		||||
      CTL_KERN,
 | 
			
		||||
      KERN_CPTIME,
 | 
			
		||||
        CTL_KERN,
 | 
			
		||||
        KERN_CPTIME,
 | 
			
		||||
    };
 | 
			
		||||
    if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
 | 
			
		||||
    if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), sum_cp_time, &sum_sz, NULL, 0)) {
 | 
			
		||||
      throw std::runtime_error("sysctl kern.cp_time failed");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -62,14 +65,14 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
 | 
			
		||||
  sz /= ncpu + 1;
 | 
			
		||||
  {
 | 
			
		||||
    int mib[] = {
 | 
			
		||||
      CTL_KERN,
 | 
			
		||||
      KERN_CPTIME2,
 | 
			
		||||
      0,
 | 
			
		||||
        CTL_KERN,
 | 
			
		||||
        KERN_CPTIME2,
 | 
			
		||||
        0,
 | 
			
		||||
    };
 | 
			
		||||
    for (int cpu = 0; cpu < ncpu; cpu++) {
 | 
			
		||||
      mib[2] = cpu;
 | 
			
		||||
      pcp_time += CPUSTATES;
 | 
			
		||||
      if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
 | 
			
		||||
      if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), pcp_time, &sz, NULL, 0)) {
 | 
			
		||||
        throw std::runtime_error("sysctl kern.cp_time2 failed");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -101,7 +104,8 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
 | 
			
		||||
std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
 | 
			
		||||
  static std::vector<float> frequencies;
 | 
			
		||||
  if (frequencies.empty()) {
 | 
			
		||||
    spdlog::warn("cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
 | 
			
		||||
    spdlog::warn(
 | 
			
		||||
        "cpu/bsd: parseCpuFrequencies is not implemented, expect garbage in {*_frequency}");
 | 
			
		||||
    frequencies.push_back(NAN);
 | 
			
		||||
  }
 | 
			
		||||
  return frequencies;
 | 
			
		||||
 
 | 
			
		||||
@@ -46,11 +46,11 @@ auto waybar::modules::Cpu::update() -> void {
 | 
			
		||||
    store.push_back(fmt::arg("min_frequency", min_frequency));
 | 
			
		||||
    store.push_back(fmt::arg("avg_frequency", avg_frequency));
 | 
			
		||||
    for (size_t i = 1; i < cpu_usage.size(); ++i) {
 | 
			
		||||
	    auto core_i = i - 1;
 | 
			
		||||
	    auto core_format = fmt::format("usage{}", core_i);
 | 
			
		||||
	    store.push_back(fmt::arg(core_format.c_str(), cpu_usage[i]));
 | 
			
		||||
	    auto icon_format = fmt::format("icon{}", core_i);
 | 
			
		||||
	    store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
 | 
			
		||||
      auto core_i = i - 1;
 | 
			
		||||
      auto core_format = fmt::format("usage{}", core_i);
 | 
			
		||||
      store.push_back(fmt::arg(core_format.c_str(), cpu_usage[i]));
 | 
			
		||||
      auto icon_format = fmt::format("icon{}", core_i);
 | 
			
		||||
      store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons)));
 | 
			
		||||
    }
 | 
			
		||||
    label_.set_markup(fmt::vformat(format, store));
 | 
			
		||||
  }
 | 
			
		||||
@@ -73,14 +73,14 @@ std::tuple<std::vector<uint16_t>, std::string> waybar::modules::Cpu::getCpuUsage
 | 
			
		||||
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
 | 
			
		||||
  }
 | 
			
		||||
  std::vector<std::tuple<size_t, size_t>> curr_times = parseCpuinfo();
 | 
			
		||||
  std::string                             tooltip;
 | 
			
		||||
  std::vector<uint16_t>                   usage;
 | 
			
		||||
  std::string tooltip;
 | 
			
		||||
  std::vector<uint16_t> usage;
 | 
			
		||||
  for (size_t i = 0; i < curr_times.size(); ++i) {
 | 
			
		||||
    auto [curr_idle, curr_total] = curr_times[i];
 | 
			
		||||
    auto [prev_idle, prev_total] = prev_times_[i];
 | 
			
		||||
    const float delta_idle = curr_idle - prev_idle;
 | 
			
		||||
    const float delta_total = curr_total - prev_total;
 | 
			
		||||
    uint16_t    tmp = 100 * (1 - delta_idle / delta_total);
 | 
			
		||||
    uint16_t tmp = 100 * (1 - delta_idle / delta_total);
 | 
			
		||||
    if (i == 0) {
 | 
			
		||||
      tooltip = fmt::format("Total: {}%", tmp);
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -95,12 +95,13 @@ std::tuple<std::vector<uint16_t>, std::string> waybar::modules::Cpu::getCpuUsage
 | 
			
		||||
std::tuple<float, float, float> waybar::modules::Cpu::getCpuFrequency() {
 | 
			
		||||
  std::vector<float> frequencies = parseCpuFrequencies();
 | 
			
		||||
  auto [min, max] = std::minmax_element(std::begin(frequencies), std::end(frequencies));
 | 
			
		||||
  float avg_frequency = std::accumulate(std::begin(frequencies), std::end(frequencies), 0.0) / frequencies.size();
 | 
			
		||||
  float avg_frequency =
 | 
			
		||||
      std::accumulate(std::begin(frequencies), std::end(frequencies), 0.0) / frequencies.size();
 | 
			
		||||
 | 
			
		||||
  // Round frequencies with double decimal precision to get GHz
 | 
			
		||||
  float max_frequency = std::ceil(*max / 10.0) / 100.0;
 | 
			
		||||
  float min_frequency = std::ceil(*min / 10.0) / 100.0;
 | 
			
		||||
  avg_frequency = std::ceil(avg_frequency / 10.0) / 100.0;
 | 
			
		||||
 | 
			
		||||
  return { max_frequency, min_frequency, avg_frequency };
 | 
			
		||||
  return {max_frequency, min_frequency, avg_frequency};
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
 | 
			
		||||
#include "modules/cpu.hpp"
 | 
			
		||||
 | 
			
		||||
std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
 | 
			
		||||
@@ -8,12 +9,12 @@ std::vector<std::tuple<size_t, size_t>> waybar::modules::Cpu::parseCpuinfo() {
 | 
			
		||||
    throw std::runtime_error("Can't open " + data_dir_);
 | 
			
		||||
  }
 | 
			
		||||
  std::vector<std::tuple<size_t, size_t>> cpuinfo;
 | 
			
		||||
  std::string                             line;
 | 
			
		||||
  std::string line;
 | 
			
		||||
  while (getline(info, line)) {
 | 
			
		||||
    if (line.substr(0, 3).compare("cpu") != 0) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    std::stringstream   sline(line.substr(5));
 | 
			
		||||
    std::stringstream sline(line.substr(5));
 | 
			
		||||
    std::vector<size_t> times;
 | 
			
		||||
    for (size_t time = 0; sline >> time; times.push_back(time))
 | 
			
		||||
      ;
 | 
			
		||||
@@ -51,12 +52,9 @@ std::vector<float> waybar::modules::Cpu::parseCpuFrequencies() {
 | 
			
		||||
  if (frequencies.size() <= 0) {
 | 
			
		||||
    std::string cpufreq_dir = "/sys/devices/system/cpu/cpufreq";
 | 
			
		||||
    if (std::filesystem::exists(cpufreq_dir)) {
 | 
			
		||||
      std::vector<std::string> frequency_files = {
 | 
			
		||||
        "/cpuinfo_min_freq",
 | 
			
		||||
        "/cpuinfo_max_freq"
 | 
			
		||||
      };
 | 
			
		||||
      for (auto& p: std::filesystem::directory_iterator(cpufreq_dir)) {
 | 
			
		||||
        for (auto freq_file: frequency_files) {
 | 
			
		||||
      std::vector<std::string> frequency_files = {"/cpuinfo_min_freq", "/cpuinfo_max_freq"};
 | 
			
		||||
      for (auto& p : std::filesystem::directory_iterator(cpufreq_dir)) {
 | 
			
		||||
        for (auto freq_file : frequency_files) {
 | 
			
		||||
          std::string freq_file_path = p.path().string() + freq_file;
 | 
			
		||||
          if (std::filesystem::exists(freq_file_path)) {
 | 
			
		||||
            std::string freq_value;
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ void waybar::modules::Custom::continuousWorker() {
 | 
			
		||||
    throw std::runtime_error("Unable to open " + cmd);
 | 
			
		||||
  }
 | 
			
		||||
  thread_ = [this, cmd] {
 | 
			
		||||
    char*  buff = nullptr;
 | 
			
		||||
    char* buff = nullptr;
 | 
			
		||||
    size_t len = 0;
 | 
			
		||||
    if (getline(&buff, &len, fp_) == -1) {
 | 
			
		||||
      int exit_code = 1;
 | 
			
		||||
@@ -120,9 +120,7 @@ auto waybar::modules::Custom::update() -> void {
 | 
			
		||||
    } else {
 | 
			
		||||
      parseOutputRaw();
 | 
			
		||||
    }
 | 
			
		||||
    auto str = fmt::format(format_,
 | 
			
		||||
                           text_,
 | 
			
		||||
                           fmt::arg("alt", alt_),
 | 
			
		||||
    auto str = fmt::format(format_, text_, fmt::arg("alt", alt_),
 | 
			
		||||
                           fmt::arg("icon", getIcon(percentage_, alt_)),
 | 
			
		||||
                           fmt::arg("percentage", percentage_));
 | 
			
		||||
    if (str.empty()) {
 | 
			
		||||
@@ -156,8 +154,8 @@ auto waybar::modules::Custom::update() -> void {
 | 
			
		||||
 | 
			
		||||
void waybar::modules::Custom::parseOutputRaw() {
 | 
			
		||||
  std::istringstream output(output_.out);
 | 
			
		||||
  std::string        line;
 | 
			
		||||
  int                i = 0;
 | 
			
		||||
  std::string line;
 | 
			
		||||
  int i = 0;
 | 
			
		||||
  while (getline(output, line)) {
 | 
			
		||||
    if (i == 0) {
 | 
			
		||||
      if (config_["escape"].isBool() && config_["escape"].asBool()) {
 | 
			
		||||
@@ -180,7 +178,7 @@ void waybar::modules::Custom::parseOutputRaw() {
 | 
			
		||||
 | 
			
		||||
void waybar::modules::Custom::parseOutputJson() {
 | 
			
		||||
  std::istringstream output(output_.out);
 | 
			
		||||
  std::string        line;
 | 
			
		||||
  std::string line;
 | 
			
		||||
  class_.clear();
 | 
			
		||||
  while (getline(output, line)) {
 | 
			
		||||
    auto parsed = parser_.parse(line);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,7 @@
 | 
			
		||||
using namespace waybar::util;
 | 
			
		||||
 | 
			
		||||
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
 | 
			
		||||
    : ALabel(config, "disk", id, "{}%", 30)
 | 
			
		||||
    , path_("/")
 | 
			
		||||
{
 | 
			
		||||
    : ALabel(config, "disk", id, "{}%", 30), path_("/") {
 | 
			
		||||
  thread_ = [this] {
 | 
			
		||||
    dp.emit();
 | 
			
		||||
    thread_.sleep_for(interval_);
 | 
			
		||||
@@ -28,7 +26,8 @@ auto waybar::modules::Disk::update() -> void {
 | 
			
		||||
      unsigned long  f_fsid;     // filesystem ID
 | 
			
		||||
      unsigned long  f_flag;     // mount flags
 | 
			
		||||
      unsigned long  f_namemax;  // maximum filename length
 | 
			
		||||
  }; */ stats;
 | 
			
		||||
  }; */
 | 
			
		||||
      stats;
 | 
			
		||||
  int err = statvfs(path_.c_str(), &stats);
 | 
			
		||||
 | 
			
		||||
  /* Conky options
 | 
			
		||||
@@ -59,15 +58,11 @@ auto waybar::modules::Disk::update() -> void {
 | 
			
		||||
    event_box_.hide();
 | 
			
		||||
  } else {
 | 
			
		||||
    event_box_.show();
 | 
			
		||||
    label_.set_markup(fmt::format(format
 | 
			
		||||
        , stats.f_bavail * 100 / stats.f_blocks
 | 
			
		||||
        , fmt::arg("free", free)
 | 
			
		||||
        , fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
 | 
			
		||||
        , fmt::arg("used", used)
 | 
			
		||||
        , fmt::arg("percentage_used", percentage_used)
 | 
			
		||||
        , fmt::arg("total", total)
 | 
			
		||||
        , fmt::arg("path", path_)
 | 
			
		||||
        ));
 | 
			
		||||
    label_.set_markup(
 | 
			
		||||
        fmt::format(format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
 | 
			
		||||
                    fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
 | 
			
		||||
                    fmt::arg("used", used), fmt::arg("percentage_used", percentage_used),
 | 
			
		||||
                    fmt::arg("total", total), fmt::arg("path", path_)));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (tooltipEnabled()) {
 | 
			
		||||
@@ -75,15 +70,11 @@ auto waybar::modules::Disk::update() -> void {
 | 
			
		||||
    if (config_["tooltip-format"].isString()) {
 | 
			
		||||
      tooltip_format = config_["tooltip-format"].asString();
 | 
			
		||||
    }
 | 
			
		||||
    label_.set_tooltip_text(fmt::format(tooltip_format
 | 
			
		||||
      , stats.f_bavail * 100 / stats.f_blocks
 | 
			
		||||
      , fmt::arg("free", free)
 | 
			
		||||
      , fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks)
 | 
			
		||||
      , fmt::arg("used", used)
 | 
			
		||||
      , fmt::arg("percentage_used", percentage_used)
 | 
			
		||||
      , fmt::arg("total", total)
 | 
			
		||||
      , fmt::arg("path", path_)
 | 
			
		||||
      ));
 | 
			
		||||
    label_.set_tooltip_text(
 | 
			
		||||
        fmt::format(tooltip_format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free),
 | 
			
		||||
                    fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks),
 | 
			
		||||
                    fmt::arg("used", used), fmt::arg("percentage_used", percentage_used),
 | 
			
		||||
                    fmt::arg("total", total), fmt::arg("path", path_)));
 | 
			
		||||
  }
 | 
			
		||||
  // Call parent update
 | 
			
		||||
  ALabel::update();
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
#include "util/command.hpp"
 | 
			
		||||
 | 
			
		||||
std::list<waybar::AModule*> waybar::modules::IdleInhibitor::modules;
 | 
			
		||||
bool                        waybar::modules::IdleInhibitor::status = false;
 | 
			
		||||
bool waybar::modules::IdleInhibitor::status = false;
 | 
			
		||||
 | 
			
		||||
waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& bar,
 | 
			
		||||
                                              const Json::Value& config)
 | 
			
		||||
@@ -47,7 +47,7 @@ auto waybar::modules::IdleInhibitor::update() -> void {
 | 
			
		||||
    label_.get_style_context()->remove_class("deactivated");
 | 
			
		||||
    if (idle_inhibitor_ == nullptr) {
 | 
			
		||||
      idle_inhibitor_ = zwp_idle_inhibit_manager_v1_create_inhibitor(
 | 
			
		||||
        waybar::Client::inst()->idle_inhibit_manager, bar_.surface);
 | 
			
		||||
          waybar::Client::inst()->idle_inhibit_manager, bar_.surface);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    label_.get_style_context()->remove_class("activated");
 | 
			
		||||
@@ -58,8 +58,8 @@ auto waybar::modules::IdleInhibitor::update() -> void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::string status_text = status ? "activated" : "deactivated";
 | 
			
		||||
  label_.set_markup(
 | 
			
		||||
      fmt::format(format_, fmt::arg("status", status_text), fmt::arg("icon", getIcon(0, status_text))));
 | 
			
		||||
  label_.set_markup(fmt::format(format_, fmt::arg("status", status_text),
 | 
			
		||||
                                fmt::arg("icon", getIcon(0, status_text))));
 | 
			
		||||
  label_.get_style_context()->add_class(status_text);
 | 
			
		||||
  if (tooltipEnabled()) {
 | 
			
		||||
    label_.set_tooltip_text(status_text);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,11 @@
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
using DBus = std::unique_ptr<GDBusConnection, void(*)(GDBusConnection*)>;
 | 
			
		||||
using DBus = std::unique_ptr<GDBusConnection, void (*)(GDBusConnection*)>;
 | 
			
		||||
 | 
			
		||||
auto dbus() -> DBus {
 | 
			
		||||
  GError *error = nullptr;
 | 
			
		||||
  GDBusConnection* connection =
 | 
			
		||||
      g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
 | 
			
		||||
  GError* error = nullptr;
 | 
			
		||||
  GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
 | 
			
		||||
 | 
			
		||||
  if (error) {
 | 
			
		||||
    spdlog::error("g_bus_get_sync() failed: {}", error->message);
 | 
			
		||||
@@ -20,46 +19,29 @@ auto dbus() -> DBus {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto destructor = [](GDBusConnection* connection) {
 | 
			
		||||
      GError *error = nullptr;
 | 
			
		||||
      g_dbus_connection_close_sync(connection, nullptr, &error);
 | 
			
		||||
      if (error) {
 | 
			
		||||
        spdlog::error(
 | 
			
		||||
            "g_bus_connection_close_sync failed(): {}",
 | 
			
		||||
            error->message);
 | 
			
		||||
        g_error_free(error);
 | 
			
		||||
      }
 | 
			
		||||
    GError* error = nullptr;
 | 
			
		||||
    g_dbus_connection_close_sync(connection, nullptr, &error);
 | 
			
		||||
    if (error) {
 | 
			
		||||
      spdlog::error("g_bus_connection_close_sync failed(): {}", error->message);
 | 
			
		||||
      g_error_free(error);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return DBus{connection, destructor};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
 | 
			
		||||
  GError *error = nullptr;
 | 
			
		||||
  GError* error = nullptr;
 | 
			
		||||
  GUnixFDList* fd_list;
 | 
			
		||||
  int handle;
 | 
			
		||||
 | 
			
		||||
  auto reply = g_dbus_connection_call_with_unix_fd_list_sync(bus.get(),
 | 
			
		||||
      "org.freedesktop.login1",
 | 
			
		||||
      "/org/freedesktop/login1",
 | 
			
		||||
      "org.freedesktop.login1.Manager",
 | 
			
		||||
      "Inhibit",
 | 
			
		||||
      g_variant_new(
 | 
			
		||||
          "(ssss)",
 | 
			
		||||
          inhibitors.c_str(),
 | 
			
		||||
          "waybar",
 | 
			
		||||
          "Asked by user",
 | 
			
		||||
          "block"),
 | 
			
		||||
      G_VARIANT_TYPE("(h)"),
 | 
			
		||||
      G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
      -1,
 | 
			
		||||
      nullptr,
 | 
			
		||||
      &fd_list,
 | 
			
		||||
      nullptr,
 | 
			
		||||
      &error);
 | 
			
		||||
  auto reply = g_dbus_connection_call_with_unix_fd_list_sync(
 | 
			
		||||
      bus.get(), "org.freedesktop.login1", "/org/freedesktop/login1",
 | 
			
		||||
      "org.freedesktop.login1.Manager", "Inhibit",
 | 
			
		||||
      g_variant_new("(ssss)", inhibitors.c_str(), "waybar", "Asked by user", "block"),
 | 
			
		||||
      G_VARIANT_TYPE("(h)"), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &fd_list, nullptr, &error);
 | 
			
		||||
  if (error) {
 | 
			
		||||
    spdlog::error(
 | 
			
		||||
        "g_dbus_connection_call_with_unix_fd_list_sync() failed: {}",
 | 
			
		||||
        error->message);
 | 
			
		||||
    spdlog::error("g_dbus_connection_call_with_unix_fd_list_sync() failed: {}", error->message);
 | 
			
		||||
    g_error_free(error);
 | 
			
		||||
    handle = -1;
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -74,18 +56,15 @@ auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto checkInhibitor(const std::string& inhibitor) -> const std::string& {
 | 
			
		||||
  static const auto inhibitors = std::array{
 | 
			
		||||
      "idle",
 | 
			
		||||
      "shutdown",
 | 
			
		||||
      "sleep",
 | 
			
		||||
      "handle-power-key",
 | 
			
		||||
      "handle-suspend-key",
 | 
			
		||||
      "handle-hibernate-key",
 | 
			
		||||
      "handle-lid-switch"
 | 
			
		||||
  };
 | 
			
		||||
  static const auto inhibitors = std::array{"idle",
 | 
			
		||||
                                            "shutdown",
 | 
			
		||||
                                            "sleep",
 | 
			
		||||
                                            "handle-power-key",
 | 
			
		||||
                                            "handle-suspend-key",
 | 
			
		||||
                                            "handle-hibernate-key",
 | 
			
		||||
                                            "handle-lid-switch"};
 | 
			
		||||
 | 
			
		||||
  if (std::find(inhibitors.begin(), inhibitors.end(), inhibitor)
 | 
			
		||||
          == inhibitors.end()) {
 | 
			
		||||
  if (std::find(inhibitors.begin(), inhibitors.end(), inhibitor) == inhibitors.end()) {
 | 
			
		||||
    throw std::runtime_error("invalid logind inhibitor " + inhibitor);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -114,18 +93,16 @@ auto getInhibitors(const Json::Value& config) -> std::string {
 | 
			
		||||
  return inhibitors;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules {
 | 
			
		||||
 | 
			
		||||
Inhibitor::Inhibitor(const std::string& id, const Bar& bar,
 | 
			
		||||
                     const Json::Value& config)
 | 
			
		||||
Inhibitor::Inhibitor(const std::string& id, const Bar& bar, const Json::Value& config)
 | 
			
		||||
    : ALabel(config, "inhibitor", id, "{status}", true),
 | 
			
		||||
      dbus_(::dbus()),
 | 
			
		||||
      inhibitors_(::getInhibitors(config)) {
 | 
			
		||||
  event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
 | 
			
		||||
  event_box_.signal_button_press_event().connect(
 | 
			
		||||
      sigc::mem_fun(*this, &Inhibitor::handleToggle));
 | 
			
		||||
  event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &Inhibitor::handleToggle));
 | 
			
		||||
  dp.emit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -135,18 +112,14 @@ Inhibitor::~Inhibitor() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Inhibitor::activated() -> bool {
 | 
			
		||||
  return handle_ != -1;
 | 
			
		||||
}
 | 
			
		||||
auto Inhibitor::activated() -> bool { return handle_ != -1; }
 | 
			
		||||
 | 
			
		||||
auto Inhibitor::update() -> void {
 | 
			
		||||
  std::string status_text = activated() ? "activated" : "deactivated";
 | 
			
		||||
 | 
			
		||||
  label_.get_style_context()->remove_class(
 | 
			
		||||
      activated() ? "deactivated" : "activated");
 | 
			
		||||
  label_.set_markup(
 | 
			
		||||
      fmt::format(format_, fmt::arg("status", status_text),
 | 
			
		||||
      fmt::arg("icon", getIcon(0, status_text))));
 | 
			
		||||
  label_.get_style_context()->remove_class(activated() ? "deactivated" : "activated");
 | 
			
		||||
  label_.set_markup(fmt::format(format_, fmt::arg("status", status_text),
 | 
			
		||||
                                fmt::arg("icon", getIcon(0, status_text))));
 | 
			
		||||
  label_.get_style_context()->add_class(status_text);
 | 
			
		||||
 | 
			
		||||
  if (tooltipEnabled()) {
 | 
			
		||||
@@ -172,4 +145,4 @@ auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool {
 | 
			
		||||
  return ALabel::handleToggle(e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // waybar::modules
 | 
			
		||||
}  // namespace waybar::modules
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,32 @@
 | 
			
		||||
#include "modules/keyboard_state.hpp"
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class errno_error : public std::runtime_error {
 | 
			
		||||
 public:
 | 
			
		||||
  int code;
 | 
			
		||||
  errno_error(int code, const std::string& msg)
 | 
			
		||||
    : std::runtime_error(getErrorMsg(code, msg.c_str())),
 | 
			
		||||
      code(code) {}
 | 
			
		||||
  errno_error(int code, const char* msg)
 | 
			
		||||
    : std::runtime_error(getErrorMsg(code, msg)),
 | 
			
		||||
      code(code) {}
 | 
			
		||||
      : std::runtime_error(getErrorMsg(code, msg.c_str())), code(code) {}
 | 
			
		||||
  errno_error(int code, const char* msg) : std::runtime_error(getErrorMsg(code, msg)), code(code) {}
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  static auto getErrorMsg(int err, const char* msg) -> std::string {
 | 
			
		||||
    std::string error_msg{msg};
 | 
			
		||||
    error_msg += ": ";
 | 
			
		||||
 | 
			
		||||
#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 32)
 | 
			
		||||
    // strerrorname_np gets the error code's name; it's nice to have, but it's a recent GNU extension
 | 
			
		||||
    // strerrorname_np gets the error code's name; it's nice to have, but it's a recent GNU
 | 
			
		||||
    // extension
 | 
			
		||||
    const auto errno_name = strerrorname_np(err);
 | 
			
		||||
    error_msg += errno_name;
 | 
			
		||||
    error_msg += " ";
 | 
			
		||||
@@ -67,33 +68,37 @@ auto openDevice(int fd) -> libevdev* {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto supportsLockStates(const libevdev* dev) -> bool {
 | 
			
		||||
  return libevdev_has_event_type(dev, EV_LED)
 | 
			
		||||
    && libevdev_has_event_code(dev, EV_LED, LED_NUML)
 | 
			
		||||
    && libevdev_has_event_code(dev, EV_LED, LED_CAPSL)
 | 
			
		||||
    && libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
 | 
			
		||||
  return libevdev_has_event_type(dev, EV_LED) && libevdev_has_event_code(dev, EV_LED, LED_NUML) &&
 | 
			
		||||
         libevdev_has_event_code(dev, EV_LED, LED_CAPSL) &&
 | 
			
		||||
         libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar, const Json::Value& config)
 | 
			
		||||
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar,
 | 
			
		||||
                                              const Json::Value& config)
 | 
			
		||||
    : AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()),
 | 
			
		||||
      box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
 | 
			
		||||
      numlock_label_(""),
 | 
			
		||||
      capslock_label_(""),
 | 
			
		||||
      numlock_format_(config_["format"].isString() ? config_["format"].asString()
 | 
			
		||||
                      : config_["format"]["numlock"].isString() ? config_["format"]["numlock"].asString()
 | 
			
		||||
                      : "{name} {icon}"),
 | 
			
		||||
                      : config_["format"]["numlock"].isString()
 | 
			
		||||
                          ? config_["format"]["numlock"].asString()
 | 
			
		||||
                          : "{name} {icon}"),
 | 
			
		||||
      capslock_format_(config_["format"].isString() ? config_["format"].asString()
 | 
			
		||||
                       : config_["format"]["capslock"].isString() ? config_["format"]["capslock"].asString()
 | 
			
		||||
                       : "{name} {icon}"),
 | 
			
		||||
                       : config_["format"]["capslock"].isString()
 | 
			
		||||
                           ? config_["format"]["capslock"].asString()
 | 
			
		||||
                           : "{name} {icon}"),
 | 
			
		||||
      scrolllock_format_(config_["format"].isString() ? config_["format"].asString()
 | 
			
		||||
                         : config_["format"]["scrolllock"].isString() ? config_["format"]["scrolllock"].asString()
 | 
			
		||||
                         : "{name} {icon}"),
 | 
			
		||||
      interval_(std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
 | 
			
		||||
                         : config_["format"]["scrolllock"].isString()
 | 
			
		||||
                             ? config_["format"]["scrolllock"].asString()
 | 
			
		||||
                             : "{name} {icon}"),
 | 
			
		||||
      interval_(
 | 
			
		||||
          std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
 | 
			
		||||
      icon_locked_(config_["format-icons"]["locked"].isString()
 | 
			
		||||
                   ? config_["format-icons"]["locked"].asString()
 | 
			
		||||
                   : "locked"),
 | 
			
		||||
                       ? config_["format-icons"]["locked"].asString()
 | 
			
		||||
                       : "locked"),
 | 
			
		||||
      icon_unlocked_(config_["format-icons"]["unlocked"].isString()
 | 
			
		||||
                     ? config_["format-icons"]["unlocked"].asString()
 | 
			
		||||
                     : "unlocked"),
 | 
			
		||||
                         ? config_["format-icons"]["unlocked"].asString()
 | 
			
		||||
                         : "unlocked"),
 | 
			
		||||
      fd_(0),
 | 
			
		||||
      dev_(nullptr) {
 | 
			
		||||
  box_.set_name("keyboard-state");
 | 
			
		||||
@@ -120,7 +125,7 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
 | 
			
		||||
    if (dev_dir == nullptr) {
 | 
			
		||||
      throw errno_error(errno, "Failed to open /dev/input");
 | 
			
		||||
    }
 | 
			
		||||
    dirent *ep;
 | 
			
		||||
    dirent* ep;
 | 
			
		||||
    while ((ep = readdir(dev_dir))) {
 | 
			
		||||
      if (ep->d_type != DT_CHR) continue;
 | 
			
		||||
      std::string dev_path = std::string("/dev/input/") + ep->d_name;
 | 
			
		||||
@@ -128,7 +133,7 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
 | 
			
		||||
      try {
 | 
			
		||||
        auto dev = openDevice(fd);
 | 
			
		||||
        if (supportsLockStates(dev)) {
 | 
			
		||||
          spdlog::info("Found device {} at '{}'", libevdev_get_name(dev),  dev_path);
 | 
			
		||||
          spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path);
 | 
			
		||||
          fd_ = fd;
 | 
			
		||||
          dev_ = dev;
 | 
			
		||||
          break;
 | 
			
		||||
@@ -184,9 +189,9 @@ auto waybar::modules::KeyboardState::update() -> void {
 | 
			
		||||
    const std::string& format;
 | 
			
		||||
    const char* name;
 | 
			
		||||
  } label_states[] = {
 | 
			
		||||
    {(bool) numl, numlock_label_, numlock_format_, "Num"},
 | 
			
		||||
    {(bool) capsl, capslock_label_, capslock_format_, "Caps"},
 | 
			
		||||
    {(bool) scrolll, scrolllock_label_, scrolllock_format_, "Scroll"},
 | 
			
		||||
      {(bool)numl, numlock_label_, numlock_format_, "Num"},
 | 
			
		||||
      {(bool)capsl, capslock_label_, capslock_format_, "Caps"},
 | 
			
		||||
      {(bool)scrolll, scrolllock_label_, scrolllock_format_, "Scroll"},
 | 
			
		||||
  };
 | 
			
		||||
  for (auto& label_state : label_states) {
 | 
			
		||||
    std::string text;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,17 @@
 | 
			
		||||
#include "modules/memory.hpp"
 | 
			
		||||
 | 
			
		||||
// clang-format off
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/sysctl.h>
 | 
			
		||||
#include <unistd.h>           // getpagesize
 | 
			
		||||
// clang-format on
 | 
			
		||||
#include <unistd.h>  // getpagesize
 | 
			
		||||
 | 
			
		||||
#include "modules/memory.hpp"
 | 
			
		||||
 | 
			
		||||
#if defined(__DragonFly__)
 | 
			
		||||
#  include <sys/vmmeter.h>    // struct vmstats
 | 
			
		||||
#include <sys/vmmeter.h>  // struct vmstats
 | 
			
		||||
#elif defined(__NetBSD__)
 | 
			
		||||
#  include <uvm/uvm_extern.h> // struct uvmexp_sysctl
 | 
			
		||||
#include <uvm/uvm_extern.h>  // struct uvmexp_sysctl
 | 
			
		||||
#elif defined(__OpenBSD__)
 | 
			
		||||
#  include <uvm/uvmexp.h>     // struct uvmexp
 | 
			
		||||
#include <uvm/uvmexp.h>  // struct uvmexp
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint64_t get_total_memory() {
 | 
			
		||||
@@ -43,33 +45,27 @@ static uint64_t get_free_memory() {
 | 
			
		||||
  if (sysctlbyname("vm.vmstats", &vms, &sz, NULL, 0)) {
 | 
			
		||||
    throw std::runtime_error("sysctl vm.vmstats failed");
 | 
			
		||||
  }
 | 
			
		||||
  return static_cast<uint64_t>
 | 
			
		||||
    (vms.v_free_count + vms.v_inactive_count + vms.v_cache_count)
 | 
			
		||||
    * getpagesize();
 | 
			
		||||
  return static_cast<uint64_t>(vms.v_free_count + vms.v_inactive_count + vms.v_cache_count) *
 | 
			
		||||
         getpagesize();
 | 
			
		||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 | 
			
		||||
  u_int v_free_count = 0, v_inactive_count = 0, v_cache_count = 0;
 | 
			
		||||
  size_t sz = sizeof(u_int);
 | 
			
		||||
  sysctlbyname("vm.stats.vm.v_free_count",
 | 
			
		||||
               &v_free_count, &sz, NULL, 0);
 | 
			
		||||
  sysctlbyname("vm.stats.vm.v_inactive_count",
 | 
			
		||||
               &v_inactive_count, &sz, NULL, 0);
 | 
			
		||||
  sysctlbyname("vm.stats.vm.v_cache_count",
 | 
			
		||||
               &v_cache_count, &sz, NULL, 0);
 | 
			
		||||
  return static_cast<uint64_t>
 | 
			
		||||
    (v_free_count + v_inactive_count + v_cache_count)
 | 
			
		||||
    * getpagesize();
 | 
			
		||||
  sysctlbyname("vm.stats.vm.v_free_count", &v_free_count, &sz, NULL, 0);
 | 
			
		||||
  sysctlbyname("vm.stats.vm.v_inactive_count", &v_inactive_count, &sz, NULL, 0);
 | 
			
		||||
  sysctlbyname("vm.stats.vm.v_cache_count", &v_cache_count, &sz, NULL, 0);
 | 
			
		||||
  return static_cast<uint64_t>(v_free_count + v_inactive_count + v_cache_count) * getpagesize();
 | 
			
		||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
 | 
			
		||||
#ifdef VM_UVMEXP2
 | 
			
		||||
#  undef VM_UVMEXP
 | 
			
		||||
#  define VM_UVMEXP VM_UVMEXP2
 | 
			
		||||
#  define uvmexp uvmexp_sysctl
 | 
			
		||||
#undef VM_UVMEXP
 | 
			
		||||
#define VM_UVMEXP VM_UVMEXP2
 | 
			
		||||
#define uvmexp uvmexp_sysctl
 | 
			
		||||
#else
 | 
			
		||||
#  define filepages vnodepages
 | 
			
		||||
#  define execpages vtextpages
 | 
			
		||||
#define filepages vnodepages
 | 
			
		||||
#define execpages vtextpages
 | 
			
		||||
#endif
 | 
			
		||||
  int mib[] = {
 | 
			
		||||
    CTL_VM,
 | 
			
		||||
    VM_UVMEXP,
 | 
			
		||||
      CTL_VM,
 | 
			
		||||
      VM_UVMEXP,
 | 
			
		||||
  };
 | 
			
		||||
  u_int miblen = sizeof(mib) / sizeof(mib[0]);
 | 
			
		||||
  struct uvmexp uvmexp;
 | 
			
		||||
@@ -77,9 +73,9 @@ static uint64_t get_free_memory() {
 | 
			
		||||
  if (sysctl(mib, miblen, &uvmexp, &sz, NULL, 0)) {
 | 
			
		||||
    throw std::runtime_error("sysctl vm.uvmexp failed");
 | 
			
		||||
  }
 | 
			
		||||
  return static_cast<uint64_t>
 | 
			
		||||
    (uvmexp.free + uvmexp.inactive + uvmexp.filepages + uvmexp.execpages)
 | 
			
		||||
    * uvmexp.pagesize;
 | 
			
		||||
  return static_cast<uint64_t>(uvmexp.free + uvmexp.inactive + uvmexp.filepages +
 | 
			
		||||
                               uvmexp.execpages) *
 | 
			
		||||
         uvmexp.pagesize;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@ auto waybar::modules::Memory::update() -> void {
 | 
			
		||||
  if (memtotal > 0 && memfree >= 0) {
 | 
			
		||||
    auto total_ram_gigabytes = memtotal / std::pow(1024, 2);
 | 
			
		||||
    auto total_swap_gigabytes = swaptotal / std::pow(1024, 2);
 | 
			
		||||
    int  used_ram_percentage = 100 * (memtotal - memfree) / memtotal;
 | 
			
		||||
    int  used_swap_percentage = 0;
 | 
			
		||||
    int used_ram_percentage = 100 * (memtotal - memfree) / memtotal;
 | 
			
		||||
    int used_swap_percentage = 0;
 | 
			
		||||
    if (swaptotal && swapfree) {
 | 
			
		||||
      used_swap_percentage = 100 * (swaptotal - swapfree) / swaptotal;
 | 
			
		||||
    }
 | 
			
		||||
@@ -54,32 +54,25 @@ auto waybar::modules::Memory::update() -> void {
 | 
			
		||||
    } else {
 | 
			
		||||
      event_box_.show();
 | 
			
		||||
      auto icons = std::vector<std::string>{state};
 | 
			
		||||
      label_.set_markup(fmt::format(format,
 | 
			
		||||
                                    used_ram_percentage,
 | 
			
		||||
                                    fmt::arg("icon", getIcon(used_ram_percentage, icons)),
 | 
			
		||||
                                    fmt::arg("total", total_ram_gigabytes),
 | 
			
		||||
                                    fmt::arg("swapTotal", total_swap_gigabytes),
 | 
			
		||||
                                    fmt::arg("percentage", used_ram_percentage),
 | 
			
		||||
                                    fmt::arg("swapPercentage", used_swap_percentage),
 | 
			
		||||
                                    fmt::arg("used", used_ram_gigabytes),
 | 
			
		||||
                                    fmt::arg("swapUsed", used_swap_gigabytes),
 | 
			
		||||
                                    fmt::arg("avail", available_ram_gigabytes),
 | 
			
		||||
                                    fmt::arg("swapAvail", available_swap_gigabytes)));
 | 
			
		||||
      label_.set_markup(fmt::format(
 | 
			
		||||
          format, used_ram_percentage, fmt::arg("icon", getIcon(used_ram_percentage, icons)),
 | 
			
		||||
          fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes),
 | 
			
		||||
          fmt::arg("percentage", used_ram_percentage),
 | 
			
		||||
          fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram_gigabytes),
 | 
			
		||||
          fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes),
 | 
			
		||||
          fmt::arg("swapAvail", available_swap_gigabytes)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (tooltipEnabled()) {
 | 
			
		||||
      if (config_["tooltip-format"].isString()) {
 | 
			
		||||
        auto tooltip_format = config_["tooltip-format"].asString();
 | 
			
		||||
        label_.set_tooltip_text(fmt::format(tooltip_format,
 | 
			
		||||
                                            used_ram_percentage,
 | 
			
		||||
                                            fmt::arg("total", total_ram_gigabytes),
 | 
			
		||||
                                            fmt::arg("swapTotal", total_swap_gigabytes),
 | 
			
		||||
                                            fmt::arg("percentage", used_ram_percentage),
 | 
			
		||||
                                            fmt::arg("swapPercentage", used_swap_percentage),
 | 
			
		||||
                                            fmt::arg("used", used_ram_gigabytes),
 | 
			
		||||
                                            fmt::arg("swapUsed", used_swap_gigabytes),
 | 
			
		||||
                                            fmt::arg("avail", available_ram_gigabytes),
 | 
			
		||||
                                            fmt::arg("swapAvail", available_swap_gigabytes)));
 | 
			
		||||
        label_.set_tooltip_text(fmt::format(
 | 
			
		||||
            tooltip_format, used_ram_percentage, fmt::arg("total", total_ram_gigabytes),
 | 
			
		||||
            fmt::arg("swapTotal", total_swap_gigabytes),
 | 
			
		||||
            fmt::arg("percentage", used_ram_percentage),
 | 
			
		||||
            fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram_gigabytes),
 | 
			
		||||
            fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes),
 | 
			
		||||
            fmt::arg("swapAvail", available_swap_gigabytes)));
 | 
			
		||||
      } else {
 | 
			
		||||
        label_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1));
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@ static unsigned zfsArcSize() {
 | 
			
		||||
  std::ifstream zfs_arc_stats{"/proc/spl/kstat/zfs/arcstats"};
 | 
			
		||||
 | 
			
		||||
  if (zfs_arc_stats.is_open()) {
 | 
			
		||||
    std::string   name;
 | 
			
		||||
    std::string   type;
 | 
			
		||||
    std::string name;
 | 
			
		||||
    std::string type;
 | 
			
		||||
    unsigned long data{0};
 | 
			
		||||
 | 
			
		||||
    std::string line;
 | 
			
		||||
@@ -23,7 +23,7 @@ static unsigned zfsArcSize() {
 | 
			
		||||
 | 
			
		||||
void waybar::modules::Memory::parseMeminfo() {
 | 
			
		||||
  const std::string data_dir_ = "/proc/meminfo";
 | 
			
		||||
  std::ifstream     info(data_dir_);
 | 
			
		||||
  std::ifstream info(data_dir_);
 | 
			
		||||
  if (!info.is_open()) {
 | 
			
		||||
    throw std::runtime_error("Can't open " + data_dir_);
 | 
			
		||||
  }
 | 
			
		||||
@@ -35,7 +35,7 @@ void waybar::modules::Memory::parseMeminfo() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string name = line.substr(0, posDelim);
 | 
			
		||||
    int64_t     value = std::stol(line.substr(posDelim + 1));
 | 
			
		||||
    int64_t value = std::stol(line.substr(posDelim + 1));
 | 
			
		||||
    meminfo_[name] = value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
#include "modules/mpd/mpd.hpp"
 | 
			
		||||
 | 
			
		||||
#include <fmt/chrono.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <glibmm/ustring.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
#include "modules/mpd/state.hpp"
 | 
			
		||||
#if defined(MPD_NOINLINE)
 | 
			
		||||
namespace waybar::modules {
 | 
			
		||||
@@ -98,9 +99,9 @@ void waybar::modules::MPD::setLabel() {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto format = format_;
 | 
			
		||||
  Glib::ustring        artist, album_artist, album, title;
 | 
			
		||||
  std::string          date;
 | 
			
		||||
  int                  song_pos = 0, queue_length = 0, volume = 0;
 | 
			
		||||
  Glib::ustring artist, album_artist, album, title;
 | 
			
		||||
  std::string date;
 | 
			
		||||
  int song_pos = 0, queue_length = 0, volume = 0;
 | 
			
		||||
  std::chrono::seconds elapsedTime, totalTime;
 | 
			
		||||
 | 
			
		||||
  std::string stateIcon = "";
 | 
			
		||||
@@ -139,37 +140,32 @@ void waybar::modules::MPD::setLabel() {
 | 
			
		||||
    totalTime = std::chrono::seconds(mpd_status_get_total_time(status_.get()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool        consumeActivated = mpd_status_get_consume(status_.get());
 | 
			
		||||
  bool consumeActivated = mpd_status_get_consume(status_.get());
 | 
			
		||||
  std::string consumeIcon = getOptionIcon("consume", consumeActivated);
 | 
			
		||||
  bool        randomActivated = mpd_status_get_random(status_.get());
 | 
			
		||||
  bool randomActivated = mpd_status_get_random(status_.get());
 | 
			
		||||
  std::string randomIcon = getOptionIcon("random", randomActivated);
 | 
			
		||||
  bool        repeatActivated = mpd_status_get_repeat(status_.get());
 | 
			
		||||
  bool repeatActivated = mpd_status_get_repeat(status_.get());
 | 
			
		||||
  std::string repeatIcon = getOptionIcon("repeat", repeatActivated);
 | 
			
		||||
  bool        singleActivated = mpd_status_get_single(status_.get());
 | 
			
		||||
  bool singleActivated = mpd_status_get_single(status_.get());
 | 
			
		||||
  std::string singleIcon = getOptionIcon("single", singleActivated);
 | 
			
		||||
  if (config_["artist-len"].isInt()) artist = artist.substr(0, config_["artist-len"].asInt());
 | 
			
		||||
  if (config_["album-artist-len"].isInt()) album_artist = album_artist.substr(0, config_["album-artist-len"].asInt());
 | 
			
		||||
  if (config_["album-artist-len"].isInt())
 | 
			
		||||
    album_artist = album_artist.substr(0, config_["album-artist-len"].asInt());
 | 
			
		||||
  if (config_["album-len"].isInt()) album = album.substr(0, config_["album-len"].asInt());
 | 
			
		||||
  if (config_["title-len"].isInt()) title = title.substr(0,config_["title-len"].asInt());
 | 
			
		||||
  if (config_["title-len"].isInt()) title = title.substr(0, config_["title-len"].asInt());
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    label_.set_markup(
 | 
			
		||||
        fmt::format(format,
 | 
			
		||||
                    fmt::arg("artist", Glib::Markup::escape_text(artist).raw()),
 | 
			
		||||
        fmt::format(format, fmt::arg("artist", Glib::Markup::escape_text(artist).raw()),
 | 
			
		||||
                    fmt::arg("albumArtist", Glib::Markup::escape_text(album_artist).raw()),
 | 
			
		||||
                    fmt::arg("album", Glib::Markup::escape_text(album).raw()),
 | 
			
		||||
                    fmt::arg("title", Glib::Markup::escape_text(title).raw()),
 | 
			
		||||
                    fmt::arg("date", Glib::Markup::escape_text(date).raw()),
 | 
			
		||||
                    fmt::arg("volume", volume),
 | 
			
		||||
                    fmt::arg("elapsedTime", elapsedTime),
 | 
			
		||||
                    fmt::arg("totalTime", totalTime),
 | 
			
		||||
                    fmt::arg("songPosition", song_pos),
 | 
			
		||||
                    fmt::arg("queueLength", queue_length),
 | 
			
		||||
                    fmt::arg("stateIcon", stateIcon),
 | 
			
		||||
                    fmt::arg("consumeIcon", consumeIcon),
 | 
			
		||||
                    fmt::arg("randomIcon", randomIcon),
 | 
			
		||||
                    fmt::arg("repeatIcon", repeatIcon),
 | 
			
		||||
                    fmt::arg("singleIcon", singleIcon)));
 | 
			
		||||
                    fmt::arg("volume", volume), fmt::arg("elapsedTime", elapsedTime),
 | 
			
		||||
                    fmt::arg("totalTime", totalTime), fmt::arg("songPosition", song_pos),
 | 
			
		||||
                    fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon),
 | 
			
		||||
                    fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon),
 | 
			
		||||
                    fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon)));
 | 
			
		||||
  } catch (fmt::format_error const& e) {
 | 
			
		||||
    spdlog::warn("mpd: format error: {}", e.what());
 | 
			
		||||
  }
 | 
			
		||||
@@ -179,22 +175,15 @@ void waybar::modules::MPD::setLabel() {
 | 
			
		||||
    tooltip_format = config_["tooltip-format"].isString() ? config_["tooltip-format"].asString()
 | 
			
		||||
                                                          : "MPD (connected)";
 | 
			
		||||
    try {
 | 
			
		||||
      auto tooltip_text = fmt::format(tooltip_format,
 | 
			
		||||
                                      fmt::arg("artist", artist.raw()),
 | 
			
		||||
                                      fmt::arg("albumArtist", album_artist.raw()),
 | 
			
		||||
                                      fmt::arg("album", album.raw()),
 | 
			
		||||
                                      fmt::arg("title", title.raw()),
 | 
			
		||||
                                      fmt::arg("date", date),
 | 
			
		||||
                                      fmt::arg("volume", volume),
 | 
			
		||||
                                      fmt::arg("elapsedTime", elapsedTime),
 | 
			
		||||
                                      fmt::arg("totalTime", totalTime),
 | 
			
		||||
                                      fmt::arg("songPosition", song_pos),
 | 
			
		||||
                                      fmt::arg("queueLength", queue_length),
 | 
			
		||||
                                      fmt::arg("stateIcon", stateIcon),
 | 
			
		||||
                                      fmt::arg("consumeIcon", consumeIcon),
 | 
			
		||||
                                      fmt::arg("randomIcon", randomIcon),
 | 
			
		||||
                                      fmt::arg("repeatIcon", repeatIcon),
 | 
			
		||||
                                      fmt::arg("singleIcon", singleIcon));
 | 
			
		||||
      auto tooltip_text =
 | 
			
		||||
          fmt::format(tooltip_format, fmt::arg("artist", artist.raw()),
 | 
			
		||||
                      fmt::arg("albumArtist", album_artist.raw()), fmt::arg("album", album.raw()),
 | 
			
		||||
                      fmt::arg("title", title.raw()), fmt::arg("date", date),
 | 
			
		||||
                      fmt::arg("volume", volume), fmt::arg("elapsedTime", elapsedTime),
 | 
			
		||||
                      fmt::arg("totalTime", totalTime), fmt::arg("songPosition", song_pos),
 | 
			
		||||
                      fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon),
 | 
			
		||||
                      fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon),
 | 
			
		||||
                      fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon));
 | 
			
		||||
      label_.set_tooltip_text(tooltip_text);
 | 
			
		||||
    } catch (fmt::format_error const& e) {
 | 
			
		||||
      spdlog::warn("mpd: format error (tooltip): {}", e.what());
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ void Idle::update() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Idle::entry() noexcept {
 | 
			
		||||
  auto            conn = ctx_->connection().get();
 | 
			
		||||
  auto conn = ctx_->connection().get();
 | 
			
		||||
  assert(conn != nullptr);
 | 
			
		||||
 | 
			
		||||
  if (!mpd_send_idle_mask(
 | 
			
		||||
@@ -61,8 +61,7 @@ void Idle::entry() noexcept {
 | 
			
		||||
    spdlog::debug("mpd: Idle: watching FD");
 | 
			
		||||
    sigc::slot<bool, Glib::IOCondition const&> idle_slot = sigc::mem_fun(*this, &Idle::on_io);
 | 
			
		||||
    idle_connection_ =
 | 
			
		||||
        Glib::signal_io().connect(idle_slot,
 | 
			
		||||
                                  mpd_connection_get_fd(conn),
 | 
			
		||||
        Glib::signal_io().connect(idle_slot, mpd_connection_get_fd(conn),
 | 
			
		||||
                                  Glib::IO_IN | Glib::IO_PRI | Glib::IO_ERR | Glib::IO_HUP);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -75,7 +74,7 @@ void Idle::exit() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Idle::on_io(Glib::IOCondition const&) {
 | 
			
		||||
  auto                         conn = ctx_->connection().get();
 | 
			
		||||
  auto conn = ctx_->connection().get();
 | 
			
		||||
 | 
			
		||||
  // callback should do this:
 | 
			
		||||
  enum mpd_idle events = mpd_recv_idle(conn, /* ignore_timeout?= */ false);
 | 
			
		||||
@@ -193,7 +192,7 @@ void Paused::exit() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Paused::on_timer() {
 | 
			
		||||
  bool                         rc = true;
 | 
			
		||||
  bool rc = true;
 | 
			
		||||
 | 
			
		||||
  // Attempt to connect with MPD.
 | 
			
		||||
  try {
 | 
			
		||||
@@ -264,7 +263,7 @@ void Stopped::exit() noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Stopped::on_timer() {
 | 
			
		||||
  bool                         rc = true;
 | 
			
		||||
  bool rc = true;
 | 
			
		||||
 | 
			
		||||
  // Attempt to connect with MPD.
 | 
			
		||||
  try {
 | 
			
		||||
@@ -327,8 +326,7 @@ void Disconnected::arm_timer(int interval) noexcept {
 | 
			
		||||
 | 
			
		||||
  // register timer
 | 
			
		||||
  sigc::slot<bool> timer_slot = sigc::mem_fun(*this, &Disconnected::on_timer);
 | 
			
		||||
  timer_connection_ =
 | 
			
		||||
      Glib::signal_timeout().connect(timer_slot, interval);
 | 
			
		||||
  timer_connection_ = Glib::signal_timeout().connect(timer_slot, interval);
 | 
			
		||||
  spdlog::debug("mpd: Disconnected: enabled interval timer.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -345,9 +343,7 @@ void Disconnected::entry() noexcept {
 | 
			
		||||
  arm_timer(1'000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Disconnected::exit() noexcept {
 | 
			
		||||
  disarm_timer();
 | 
			
		||||
}
 | 
			
		||||
void Disconnected::exit() noexcept { disarm_timer(); }
 | 
			
		||||
 | 
			
		||||
bool Disconnected::on_timer() {
 | 
			
		||||
  // Attempt to connect with MPD.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,14 @@
 | 
			
		||||
#include "modules/network.hpp"
 | 
			
		||||
 | 
			
		||||
#include <linux/if.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sys/eventfd.h>
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
#include "modules/network.hpp"
 | 
			
		||||
#include "util/format.hpp"
 | 
			
		||||
#ifdef WANT_RFKILL
 | 
			
		||||
#include "util/rfkill.hpp"
 | 
			
		||||
@@ -39,7 +40,7 @@ waybar::modules::Network::readBandwidthUsage() {
 | 
			
		||||
    std::istringstream iss(line);
 | 
			
		||||
 | 
			
		||||
    std::string ifacename;
 | 
			
		||||
    iss >> ifacename;  // ifacename contains "eth0:"
 | 
			
		||||
    iss >> ifacename;      // ifacename contains "eth0:"
 | 
			
		||||
    ifacename.pop_back();  // remove trailing ':'
 | 
			
		||||
    if (!checkInterface(ifacename)) {
 | 
			
		||||
      continue;
 | 
			
		||||
@@ -58,9 +59,13 @@ waybar::modules::Network::readBandwidthUsage() {
 | 
			
		||||
    // Skip all the other columns in the received group
 | 
			
		||||
    for (int colsToSkip = 7; colsToSkip > 0; colsToSkip--) {
 | 
			
		||||
      // skip whitespace between columns
 | 
			
		||||
      while (iss.peek() == ' ') { iss.ignore(); }
 | 
			
		||||
      while (iss.peek() == ' ') {
 | 
			
		||||
        iss.ignore();
 | 
			
		||||
      }
 | 
			
		||||
      // skip the irrelevant column
 | 
			
		||||
      while (iss.peek() != ' ') { iss.ignore(); }
 | 
			
		||||
      while (iss.peek() != ' ') {
 | 
			
		||||
        iss.ignore();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // Read transmit bytes
 | 
			
		||||
    iss >> t;
 | 
			
		||||
@@ -192,7 +197,7 @@ void waybar::modules::Network::createEventSocket() {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  {
 | 
			
		||||
    auto               fd = nl_socket_get_fd(ev_sock_);
 | 
			
		||||
    auto fd = nl_socket_get_fd(ev_sock_);
 | 
			
		||||
    struct epoll_event event;
 | 
			
		||||
    memset(&event, 0, sizeof(event));
 | 
			
		||||
    event.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
 | 
			
		||||
@@ -274,8 +279,7 @@ void waybar::modules::Network::worker() {
 | 
			
		||||
const std::string waybar::modules::Network::getNetworkState() const {
 | 
			
		||||
  if (ifid_ == -1) {
 | 
			
		||||
#ifdef WANT_RFKILL
 | 
			
		||||
    if (rfkill_.getState())
 | 
			
		||||
      return "disabled";
 | 
			
		||||
    if (rfkill_.getState()) return "disabled";
 | 
			
		||||
#endif
 | 
			
		||||
    return "disconnected";
 | 
			
		||||
  }
 | 
			
		||||
@@ -287,7 +291,7 @@ const std::string waybar::modules::Network::getNetworkState() const {
 | 
			
		||||
 | 
			
		||||
auto waybar::modules::Network::update() -> void {
 | 
			
		||||
  std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
  std::string                 tooltip_format;
 | 
			
		||||
  std::string tooltip_format;
 | 
			
		||||
 | 
			
		||||
  auto bandwidth = readBandwidthUsage();
 | 
			
		||||
  auto bandwidth_down = 0ull;
 | 
			
		||||
@@ -327,17 +331,11 @@ auto waybar::modules::Network::update() -> void {
 | 
			
		||||
  getState(signal_strength_);
 | 
			
		||||
 | 
			
		||||
  auto text = fmt::format(
 | 
			
		||||
      format_,
 | 
			
		||||
      fmt::arg("essid", essid_),
 | 
			
		||||
      fmt::arg("signaldBm", signal_strength_dbm_),
 | 
			
		||||
      format_, fmt::arg("essid", essid_), fmt::arg("signaldBm", signal_strength_dbm_),
 | 
			
		||||
      fmt::arg("signalStrength", signal_strength_),
 | 
			
		||||
      fmt::arg("signalStrengthApp", signal_strength_app_),
 | 
			
		||||
      fmt::arg("ifname", ifname_),
 | 
			
		||||
      fmt::arg("netmask", netmask_),
 | 
			
		||||
      fmt::arg("ipaddr", ipaddr_),
 | 
			
		||||
      fmt::arg("gwaddr", gwaddr_),
 | 
			
		||||
      fmt::arg("cidr", cidr_),
 | 
			
		||||
      fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
 | 
			
		||||
      fmt::arg("signalStrengthApp", signal_strength_app_), fmt::arg("ifname", ifname_),
 | 
			
		||||
      fmt::arg("netmask", netmask_), fmt::arg("ipaddr", ipaddr_), fmt::arg("gwaddr", gwaddr_),
 | 
			
		||||
      fmt::arg("cidr", cidr_), fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
 | 
			
		||||
      fmt::arg("icon", getIcon(signal_strength_, state_)),
 | 
			
		||||
      fmt::arg("bandwidthDownBits", pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
 | 
			
		||||
      fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
 | 
			
		||||
@@ -359,17 +357,11 @@ auto waybar::modules::Network::update() -> void {
 | 
			
		||||
    }
 | 
			
		||||
    if (!tooltip_format.empty()) {
 | 
			
		||||
      auto tooltip_text = fmt::format(
 | 
			
		||||
          tooltip_format,
 | 
			
		||||
          fmt::arg("essid", essid_),
 | 
			
		||||
          fmt::arg("signaldBm", signal_strength_dbm_),
 | 
			
		||||
          tooltip_format, fmt::arg("essid", essid_), fmt::arg("signaldBm", signal_strength_dbm_),
 | 
			
		||||
          fmt::arg("signalStrength", signal_strength_),
 | 
			
		||||
          fmt::arg("signalStrengthApp", signal_strength_app_),
 | 
			
		||||
          fmt::arg("ifname", ifname_),
 | 
			
		||||
          fmt::arg("netmask", netmask_),
 | 
			
		||||
          fmt::arg("ipaddr", ipaddr_),
 | 
			
		||||
          fmt::arg("gwaddr", gwaddr_),
 | 
			
		||||
          fmt::arg("cidr", cidr_),
 | 
			
		||||
          fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
 | 
			
		||||
          fmt::arg("signalStrengthApp", signal_strength_app_), fmt::arg("ifname", ifname_),
 | 
			
		||||
          fmt::arg("netmask", netmask_), fmt::arg("ipaddr", ipaddr_), fmt::arg("gwaddr", gwaddr_),
 | 
			
		||||
          fmt::arg("cidr", cidr_), fmt::arg("frequency", fmt::format("{:.1f}", frequency_)),
 | 
			
		||||
          fmt::arg("icon", getIcon(signal_strength_, state_)),
 | 
			
		||||
          fmt::arg("bandwidthDownBits",
 | 
			
		||||
                   pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
 | 
			
		||||
@@ -414,286 +406,279 @@ void waybar::modules::Network::clearIface() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
 | 
			
		||||
  auto                        net = static_cast<waybar::modules::Network *>(data);
 | 
			
		||||
  auto net = static_cast<waybar::modules::Network *>(data);
 | 
			
		||||
  std::lock_guard<std::mutex> lock(net->mutex_);
 | 
			
		||||
  auto                        nh = nlmsg_hdr(msg);
 | 
			
		||||
  bool                        is_del_event = false;
 | 
			
		||||
  auto nh = nlmsg_hdr(msg);
 | 
			
		||||
  bool is_del_event = false;
 | 
			
		||||
 | 
			
		||||
  switch (nh->nlmsg_type) {
 | 
			
		||||
  case RTM_DELLINK:
 | 
			
		||||
    is_del_event = true;
 | 
			
		||||
  case RTM_NEWLINK: {
 | 
			
		||||
    struct ifinfomsg *ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
 | 
			
		||||
    ssize_t attrlen = IFLA_PAYLOAD(nh);
 | 
			
		||||
    struct rtattr *ifla = IFLA_RTA(ifi);
 | 
			
		||||
    const char *ifname = NULL;
 | 
			
		||||
    size_t ifname_len = 0;
 | 
			
		||||
    std::optional<bool> carrier;
 | 
			
		||||
    case RTM_DELLINK:
 | 
			
		||||
      is_del_event = true;
 | 
			
		||||
    case RTM_NEWLINK: {
 | 
			
		||||
      struct ifinfomsg *ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
 | 
			
		||||
      ssize_t attrlen = IFLA_PAYLOAD(nh);
 | 
			
		||||
      struct rtattr *ifla = IFLA_RTA(ifi);
 | 
			
		||||
      const char *ifname = NULL;
 | 
			
		||||
      size_t ifname_len = 0;
 | 
			
		||||
      std::optional<bool> carrier;
 | 
			
		||||
 | 
			
		||||
    if (net->ifid_ != -1 && ifi->ifi_index != net->ifid_) {
 | 
			
		||||
      return NL_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if the interface goes "down" and if we want to detect the
 | 
			
		||||
    // external interface.
 | 
			
		||||
    if (net->ifid_ != -1 && !(ifi->ifi_flags & IFF_UP)
 | 
			
		||||
        && !net->config_["interface"].isString()) {
 | 
			
		||||
      // The current interface is now down, all the routes associated with
 | 
			
		||||
      // it have been deleted, so start looking for a new default route.
 | 
			
		||||
      spdlog::debug("network: if{} down", net->ifid_);
 | 
			
		||||
      net->clearIface();
 | 
			
		||||
      net->dp.emit();
 | 
			
		||||
      net->want_route_dump_ = true;
 | 
			
		||||
      net->askForStateDump();
 | 
			
		||||
      return NL_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (; RTA_OK(ifla, attrlen); ifla = RTA_NEXT(ifla, attrlen)) {
 | 
			
		||||
      switch (ifla->rta_type) {
 | 
			
		||||
      case IFLA_IFNAME:
 | 
			
		||||
        ifname = static_cast<const char *>(RTA_DATA(ifla));
 | 
			
		||||
        ifname_len = RTA_PAYLOAD(ifla) - 1; // minus \0
 | 
			
		||||
        break;
 | 
			
		||||
      case IFLA_CARRIER: {
 | 
			
		||||
        carrier = *(char*)RTA_DATA(ifla) == 1;
 | 
			
		||||
        break;
 | 
			
		||||
      if (net->ifid_ != -1 && ifi->ifi_index != net->ifid_) {
 | 
			
		||||
        return NL_OK;
 | 
			
		||||
      }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!is_del_event && ifi->ifi_index == net->ifid_) {
 | 
			
		||||
      // Update interface information
 | 
			
		||||
      if (net->ifname_.empty() && ifname != NULL) {
 | 
			
		||||
        std::string new_ifname (ifname, ifname_len);
 | 
			
		||||
        net->ifname_ = new_ifname;
 | 
			
		||||
      }
 | 
			
		||||
      if (carrier.has_value()) {
 | 
			
		||||
        if (net->carrier_ != *carrier) {
 | 
			
		||||
          if (*carrier) {
 | 
			
		||||
            // Ask for WiFi information
 | 
			
		||||
            net->thread_timer_.wake_up();
 | 
			
		||||
          } else {
 | 
			
		||||
            // clear state related to WiFi connection
 | 
			
		||||
            net->essid_.clear();
 | 
			
		||||
            net->signal_strength_dbm_ = 0;
 | 
			
		||||
            net->signal_strength_ = 0;
 | 
			
		||||
            net->signal_strength_app_.clear();
 | 
			
		||||
            net->frequency_ = 0.0;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        net->carrier_ = carrier.value();
 | 
			
		||||
      }
 | 
			
		||||
    } else if (!is_del_event && net->ifid_ == -1) {
 | 
			
		||||
      // Checking if it's an interface we care about.
 | 
			
		||||
      std::string new_ifname (ifname, ifname_len);
 | 
			
		||||
      if (net->checkInterface(new_ifname)) {
 | 
			
		||||
        spdlog::debug("network: selecting new interface {}/{}", new_ifname, ifi->ifi_index);
 | 
			
		||||
 | 
			
		||||
        net->ifname_ = new_ifname;
 | 
			
		||||
        net->ifid_ = ifi->ifi_index;
 | 
			
		||||
        if (carrier.has_value()) {
 | 
			
		||||
          net->carrier_ = carrier.value();
 | 
			
		||||
        }
 | 
			
		||||
        net->thread_timer_.wake_up();
 | 
			
		||||
        /* An address for this new interface should be received via an
 | 
			
		||||
         * RTM_NEWADDR event either because we ask for a dump of both links
 | 
			
		||||
         * and addrs, or because this interface has just been created and
 | 
			
		||||
         * the addr will be sent after the RTM_NEWLINK event.
 | 
			
		||||
         * So we don't need to do anything. */
 | 
			
		||||
      }
 | 
			
		||||
    } else if (is_del_event && net->ifid_ >= 0) {
 | 
			
		||||
      // Our interface has been deleted, start looking/waiting for one we care.
 | 
			
		||||
      spdlog::debug("network: interface {}/{} deleted", net->ifname_, net->ifid_);
 | 
			
		||||
 | 
			
		||||
      net->clearIface();
 | 
			
		||||
      net->dp.emit();
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  case RTM_DELADDR:
 | 
			
		||||
    is_del_event = true;
 | 
			
		||||
  case RTM_NEWADDR: {
 | 
			
		||||
    struct ifaddrmsg *ifa = static_cast<struct ifaddrmsg *>(NLMSG_DATA(nh));
 | 
			
		||||
    ssize_t attrlen = IFA_PAYLOAD(nh);
 | 
			
		||||
    struct rtattr *ifa_rta = IFA_RTA(ifa);
 | 
			
		||||
 | 
			
		||||
    if ((int)ifa->ifa_index != net->ifid_) {
 | 
			
		||||
      return NL_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ifa->ifa_family != net->family_) {
 | 
			
		||||
      return NL_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We ignore address mark as scope for the link or host,
 | 
			
		||||
    // which should leave scope global addresses.
 | 
			
		||||
    if (ifa->ifa_scope >= RT_SCOPE_LINK) {
 | 
			
		||||
      return NL_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (; RTA_OK(ifa_rta, attrlen); ifa_rta = RTA_NEXT(ifa_rta, attrlen)) {
 | 
			
		||||
      switch (ifa_rta->rta_type) {
 | 
			
		||||
      case IFA_ADDRESS: {
 | 
			
		||||
        char ipaddr[INET6_ADDRSTRLEN];
 | 
			
		||||
        if (!is_del_event) {
 | 
			
		||||
          net->ipaddr_ = inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta),
 | 
			
		||||
                                   ipaddr, sizeof (ipaddr));
 | 
			
		||||
          net->cidr_ = ifa->ifa_prefixlen;
 | 
			
		||||
          switch (ifa->ifa_family) {
 | 
			
		||||
          case AF_INET: {
 | 
			
		||||
            struct in_addr netmask;
 | 
			
		||||
            netmask.s_addr = htonl(~0 << (32 - ifa->ifa_prefixlen));
 | 
			
		||||
            net->netmask_ = inet_ntop(ifa->ifa_family, &netmask,
 | 
			
		||||
                                      ipaddr, sizeof (ipaddr));
 | 
			
		||||
          }
 | 
			
		||||
          case AF_INET6: {
 | 
			
		||||
            struct in6_addr netmask;
 | 
			
		||||
            for (int i = 0; i < 16; i++) {
 | 
			
		||||
              int v = (i + 1) * 8 - ifa->ifa_prefixlen;
 | 
			
		||||
              if (v < 0) v = 0;
 | 
			
		||||
              if (v > 8) v = 8;
 | 
			
		||||
              netmask.s6_addr[i] = ~0 << v;
 | 
			
		||||
            }
 | 
			
		||||
            net->netmask_ = inet_ntop(ifa->ifa_family, &netmask,
 | 
			
		||||
                                      ipaddr, sizeof (ipaddr));
 | 
			
		||||
          }
 | 
			
		||||
          }
 | 
			
		||||
          spdlog::debug("network: {}, new addr {}/{}", net->ifname_, net->ipaddr_, net->cidr_);
 | 
			
		||||
        } else {
 | 
			
		||||
          net->ipaddr_.clear();
 | 
			
		||||
          net->cidr_ = 0;
 | 
			
		||||
          net->netmask_.clear();
 | 
			
		||||
          spdlog::debug("network: {} addr deleted {}/{}",
 | 
			
		||||
                        net->ifname_,
 | 
			
		||||
                        inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta),
 | 
			
		||||
                                  ipaddr, sizeof (ipaddr)),
 | 
			
		||||
                        ifa->ifa_prefixlen);
 | 
			
		||||
        }
 | 
			
		||||
        net->dp.emit();
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    char	temp_gw_addr[INET6_ADDRSTRLEN];
 | 
			
		||||
  case RTM_DELROUTE:
 | 
			
		||||
    is_del_event = true;
 | 
			
		||||
  case RTM_NEWROUTE: {
 | 
			
		||||
    // Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
 | 
			
		||||
    // to find the interface used to reach the outside world
 | 
			
		||||
 | 
			
		||||
    struct rtmsg  *rtm = static_cast<struct rtmsg *>(NLMSG_DATA(nh));
 | 
			
		||||
    ssize_t attrlen = RTM_PAYLOAD(nh);
 | 
			
		||||
    struct rtattr *attr = RTM_RTA(rtm);
 | 
			
		||||
    bool           has_gateway = false;
 | 
			
		||||
    bool           has_destination = false;
 | 
			
		||||
    int            temp_idx = -1;
 | 
			
		||||
    uint32_t       priority = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /* Find the message(s) concerting the main routing table, each message
 | 
			
		||||
     * corresponds to a single routing table entry.
 | 
			
		||||
     */
 | 
			
		||||
    if (rtm->rtm_table != RT_TABLE_MAIN) {
 | 
			
		||||
      return NL_OK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Parse all the attributes for a single routing table entry. */
 | 
			
		||||
    for (; RTA_OK(attr, attrlen); attr = RTA_NEXT(attr, attrlen)) {
 | 
			
		||||
      /* Determine if this routing table entry corresponds to the default
 | 
			
		||||
       * route by seeing if it has a gateway, and if a destination addr is
 | 
			
		||||
       * set, that it is all 0s.
 | 
			
		||||
       */
 | 
			
		||||
      switch(attr->rta_type) {
 | 
			
		||||
      case RTA_GATEWAY:
 | 
			
		||||
        /* The gateway of the route.
 | 
			
		||||
         *
 | 
			
		||||
         * If someone ever needs to figure out the gateway address as well,
 | 
			
		||||
         * it's here as the attribute payload.
 | 
			
		||||
         */
 | 
			
		||||
	inet_ntop(net->family_, RTA_DATA(attr), temp_gw_addr, sizeof(temp_gw_addr));
 | 
			
		||||
        has_gateway = true;
 | 
			
		||||
        break;
 | 
			
		||||
      case RTA_DST: {
 | 
			
		||||
        /* The destination address.
 | 
			
		||||
         * Should be either missing, or maybe all 0s.  Accept both.
 | 
			
		||||
         */
 | 
			
		||||
        const uint32_t nr_zeroes = (net->family_ == AF_INET) ? 4 : 16;
 | 
			
		||||
        unsigned char  c = 0;
 | 
			
		||||
        size_t         dstlen = RTA_PAYLOAD(attr);
 | 
			
		||||
        if (dstlen != nr_zeroes) {
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        for (uint32_t i = 0; i < dstlen; i += 1) {
 | 
			
		||||
          c |= *((unsigned char *)RTA_DATA(attr) + i);
 | 
			
		||||
        }
 | 
			
		||||
        has_destination = (c == 0);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case RTA_OIF:
 | 
			
		||||
        /* The output interface index. */
 | 
			
		||||
        temp_idx = *static_cast<int *>(RTA_DATA(attr));
 | 
			
		||||
        break;
 | 
			
		||||
      case RTA_PRIORITY:
 | 
			
		||||
        priority = *(uint32_t*)RTA_DATA(attr);
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if we have a default route.
 | 
			
		||||
    if (has_gateway && !has_destination && temp_idx != -1) {
 | 
			
		||||
      // Check if this is the first default route we see, or if this new
 | 
			
		||||
      // route have a higher priority.
 | 
			
		||||
      if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority))) {
 | 
			
		||||
        // Clear if's state for the case were there is a higher priority
 | 
			
		||||
        // route on a different interface.
 | 
			
		||||
        net->clearIface();
 | 
			
		||||
        net->ifid_ = temp_idx;
 | 
			
		||||
        net->route_priority = priority;
 | 
			
		||||
        net->gwaddr_ = temp_gw_addr;
 | 
			
		||||
        spdlog::debug("network: new default route via {} on if{} metric {}", temp_gw_addr, temp_idx, priority);
 | 
			
		||||
 | 
			
		||||
        /* Ask ifname associated with temp_idx as well as carrier status */
 | 
			
		||||
        struct ifinfomsg ifinfo_hdr = {
 | 
			
		||||
          .ifi_family = AF_UNSPEC,
 | 
			
		||||
          .ifi_index = temp_idx,
 | 
			
		||||
        };
 | 
			
		||||
        int err;
 | 
			
		||||
        err = nl_send_simple(net->ev_sock_, RTM_GETLINK, NLM_F_REQUEST,
 | 
			
		||||
                             &ifinfo_hdr, sizeof (ifinfo_hdr));
 | 
			
		||||
        if (err < 0) {
 | 
			
		||||
          spdlog::error("network: failed to ask link info: {}", err);
 | 
			
		||||
          /* Ask for a dump of all links instead */
 | 
			
		||||
          net->want_link_dump_ = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Also ask for the address. Asking for a addresses of a specific
 | 
			
		||||
         * interface doesn't seems to work so ask for a dump of all
 | 
			
		||||
         * addresses. */
 | 
			
		||||
        net->want_addr_dump_ = true;
 | 
			
		||||
        net->askForStateDump();
 | 
			
		||||
        net->thread_timer_.wake_up();
 | 
			
		||||
      } else if (is_del_event && temp_idx == net->ifid_
 | 
			
		||||
                 && net->route_priority == priority) {
 | 
			
		||||
        spdlog::debug("network: default route deleted {}/if{} metric {}",
 | 
			
		||||
                      net->ifname_, temp_idx, priority);
 | 
			
		||||
 | 
			
		||||
      // Check if the interface goes "down" and if we want to detect the
 | 
			
		||||
      // external interface.
 | 
			
		||||
      if (net->ifid_ != -1 && !(ifi->ifi_flags & IFF_UP) && !net->config_["interface"].isString()) {
 | 
			
		||||
        // The current interface is now down, all the routes associated with
 | 
			
		||||
        // it have been deleted, so start looking for a new default route.
 | 
			
		||||
        spdlog::debug("network: if{} down", net->ifid_);
 | 
			
		||||
        net->clearIface();
 | 
			
		||||
        net->dp.emit();
 | 
			
		||||
        /* Ask for a dump of all routes in case another one is already
 | 
			
		||||
         * setup. If there's none, there'll be an event with new one
 | 
			
		||||
         * later. */
 | 
			
		||||
        net->want_route_dump_ = true;
 | 
			
		||||
        net->askForStateDump();
 | 
			
		||||
        return NL_OK;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (; RTA_OK(ifla, attrlen); ifla = RTA_NEXT(ifla, attrlen)) {
 | 
			
		||||
        switch (ifla->rta_type) {
 | 
			
		||||
          case IFLA_IFNAME:
 | 
			
		||||
            ifname = static_cast<const char *>(RTA_DATA(ifla));
 | 
			
		||||
            ifname_len = RTA_PAYLOAD(ifla) - 1;  // minus \0
 | 
			
		||||
            break;
 | 
			
		||||
          case IFLA_CARRIER: {
 | 
			
		||||
            carrier = *(char *)RTA_DATA(ifla) == 1;
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!is_del_event && ifi->ifi_index == net->ifid_) {
 | 
			
		||||
        // Update interface information
 | 
			
		||||
        if (net->ifname_.empty() && ifname != NULL) {
 | 
			
		||||
          std::string new_ifname(ifname, ifname_len);
 | 
			
		||||
          net->ifname_ = new_ifname;
 | 
			
		||||
        }
 | 
			
		||||
        if (carrier.has_value()) {
 | 
			
		||||
          if (net->carrier_ != *carrier) {
 | 
			
		||||
            if (*carrier) {
 | 
			
		||||
              // Ask for WiFi information
 | 
			
		||||
              net->thread_timer_.wake_up();
 | 
			
		||||
            } else {
 | 
			
		||||
              // clear state related to WiFi connection
 | 
			
		||||
              net->essid_.clear();
 | 
			
		||||
              net->signal_strength_dbm_ = 0;
 | 
			
		||||
              net->signal_strength_ = 0;
 | 
			
		||||
              net->signal_strength_app_.clear();
 | 
			
		||||
              net->frequency_ = 0.0;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          net->carrier_ = carrier.value();
 | 
			
		||||
        }
 | 
			
		||||
      } else if (!is_del_event && net->ifid_ == -1) {
 | 
			
		||||
        // Checking if it's an interface we care about.
 | 
			
		||||
        std::string new_ifname(ifname, ifname_len);
 | 
			
		||||
        if (net->checkInterface(new_ifname)) {
 | 
			
		||||
          spdlog::debug("network: selecting new interface {}/{}", new_ifname, ifi->ifi_index);
 | 
			
		||||
 | 
			
		||||
          net->ifname_ = new_ifname;
 | 
			
		||||
          net->ifid_ = ifi->ifi_index;
 | 
			
		||||
          if (carrier.has_value()) {
 | 
			
		||||
            net->carrier_ = carrier.value();
 | 
			
		||||
          }
 | 
			
		||||
          net->thread_timer_.wake_up();
 | 
			
		||||
          /* An address for this new interface should be received via an
 | 
			
		||||
           * RTM_NEWADDR event either because we ask for a dump of both links
 | 
			
		||||
           * and addrs, or because this interface has just been created and
 | 
			
		||||
           * the addr will be sent after the RTM_NEWLINK event.
 | 
			
		||||
           * So we don't need to do anything. */
 | 
			
		||||
        }
 | 
			
		||||
      } else if (is_del_event && net->ifid_ >= 0) {
 | 
			
		||||
        // Our interface has been deleted, start looking/waiting for one we care.
 | 
			
		||||
        spdlog::debug("network: interface {}/{} deleted", net->ifname_, net->ifid_);
 | 
			
		||||
 | 
			
		||||
        net->clearIface();
 | 
			
		||||
        net->dp.emit();
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case RTM_DELADDR:
 | 
			
		||||
      is_del_event = true;
 | 
			
		||||
    case RTM_NEWADDR: {
 | 
			
		||||
      struct ifaddrmsg *ifa = static_cast<struct ifaddrmsg *>(NLMSG_DATA(nh));
 | 
			
		||||
      ssize_t attrlen = IFA_PAYLOAD(nh);
 | 
			
		||||
      struct rtattr *ifa_rta = IFA_RTA(ifa);
 | 
			
		||||
 | 
			
		||||
      if ((int)ifa->ifa_index != net->ifid_) {
 | 
			
		||||
        return NL_OK;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (ifa->ifa_family != net->family_) {
 | 
			
		||||
        return NL_OK;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // We ignore address mark as scope for the link or host,
 | 
			
		||||
      // which should leave scope global addresses.
 | 
			
		||||
      if (ifa->ifa_scope >= RT_SCOPE_LINK) {
 | 
			
		||||
        return NL_OK;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      for (; RTA_OK(ifa_rta, attrlen); ifa_rta = RTA_NEXT(ifa_rta, attrlen)) {
 | 
			
		||||
        switch (ifa_rta->rta_type) {
 | 
			
		||||
          case IFA_ADDRESS: {
 | 
			
		||||
            char ipaddr[INET6_ADDRSTRLEN];
 | 
			
		||||
            if (!is_del_event) {
 | 
			
		||||
              net->ipaddr_ = inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta), ipaddr, sizeof(ipaddr));
 | 
			
		||||
              net->cidr_ = ifa->ifa_prefixlen;
 | 
			
		||||
              switch (ifa->ifa_family) {
 | 
			
		||||
                case AF_INET: {
 | 
			
		||||
                  struct in_addr netmask;
 | 
			
		||||
                  netmask.s_addr = htonl(~0 << (32 - ifa->ifa_prefixlen));
 | 
			
		||||
                  net->netmask_ = inet_ntop(ifa->ifa_family, &netmask, ipaddr, sizeof(ipaddr));
 | 
			
		||||
                }
 | 
			
		||||
                case AF_INET6: {
 | 
			
		||||
                  struct in6_addr netmask;
 | 
			
		||||
                  for (int i = 0; i < 16; i++) {
 | 
			
		||||
                    int v = (i + 1) * 8 - ifa->ifa_prefixlen;
 | 
			
		||||
                    if (v < 0) v = 0;
 | 
			
		||||
                    if (v > 8) v = 8;
 | 
			
		||||
                    netmask.s6_addr[i] = ~0 << v;
 | 
			
		||||
                  }
 | 
			
		||||
                  net->netmask_ = inet_ntop(ifa->ifa_family, &netmask, ipaddr, sizeof(ipaddr));
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              spdlog::debug("network: {}, new addr {}/{}", net->ifname_, net->ipaddr_, net->cidr_);
 | 
			
		||||
            } else {
 | 
			
		||||
              net->ipaddr_.clear();
 | 
			
		||||
              net->cidr_ = 0;
 | 
			
		||||
              net->netmask_.clear();
 | 
			
		||||
              spdlog::debug("network: {} addr deleted {}/{}", net->ifname_,
 | 
			
		||||
                            inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta), ipaddr, sizeof(ipaddr)),
 | 
			
		||||
                            ifa->ifa_prefixlen);
 | 
			
		||||
            }
 | 
			
		||||
            net->dp.emit();
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      char temp_gw_addr[INET6_ADDRSTRLEN];
 | 
			
		||||
    case RTM_DELROUTE:
 | 
			
		||||
      is_del_event = true;
 | 
			
		||||
    case RTM_NEWROUTE: {
 | 
			
		||||
      // Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
 | 
			
		||||
      // to find the interface used to reach the outside world
 | 
			
		||||
 | 
			
		||||
      struct rtmsg *rtm = static_cast<struct rtmsg *>(NLMSG_DATA(nh));
 | 
			
		||||
      ssize_t attrlen = RTM_PAYLOAD(nh);
 | 
			
		||||
      struct rtattr *attr = RTM_RTA(rtm);
 | 
			
		||||
      bool has_gateway = false;
 | 
			
		||||
      bool has_destination = false;
 | 
			
		||||
      int temp_idx = -1;
 | 
			
		||||
      uint32_t priority = 0;
 | 
			
		||||
 | 
			
		||||
      /* Find the message(s) concerting the main routing table, each message
 | 
			
		||||
       * corresponds to a single routing table entry.
 | 
			
		||||
       */
 | 
			
		||||
      if (rtm->rtm_table != RT_TABLE_MAIN) {
 | 
			
		||||
        return NL_OK;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /* Parse all the attributes for a single routing table entry. */
 | 
			
		||||
      for (; RTA_OK(attr, attrlen); attr = RTA_NEXT(attr, attrlen)) {
 | 
			
		||||
        /* Determine if this routing table entry corresponds to the default
 | 
			
		||||
         * route by seeing if it has a gateway, and if a destination addr is
 | 
			
		||||
         * set, that it is all 0s.
 | 
			
		||||
         */
 | 
			
		||||
        switch (attr->rta_type) {
 | 
			
		||||
          case RTA_GATEWAY:
 | 
			
		||||
            /* The gateway of the route.
 | 
			
		||||
             *
 | 
			
		||||
             * If someone ever needs to figure out the gateway address as well,
 | 
			
		||||
             * it's here as the attribute payload.
 | 
			
		||||
             */
 | 
			
		||||
            inet_ntop(net->family_, RTA_DATA(attr), temp_gw_addr, sizeof(temp_gw_addr));
 | 
			
		||||
            has_gateway = true;
 | 
			
		||||
            break;
 | 
			
		||||
          case RTA_DST: {
 | 
			
		||||
            /* The destination address.
 | 
			
		||||
             * Should be either missing, or maybe all 0s.  Accept both.
 | 
			
		||||
             */
 | 
			
		||||
            const uint32_t nr_zeroes = (net->family_ == AF_INET) ? 4 : 16;
 | 
			
		||||
            unsigned char c = 0;
 | 
			
		||||
            size_t dstlen = RTA_PAYLOAD(attr);
 | 
			
		||||
            if (dstlen != nr_zeroes) {
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
            for (uint32_t i = 0; i < dstlen; i += 1) {
 | 
			
		||||
              c |= *((unsigned char *)RTA_DATA(attr) + i);
 | 
			
		||||
            }
 | 
			
		||||
            has_destination = (c == 0);
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
          case RTA_OIF:
 | 
			
		||||
            /* The output interface index. */
 | 
			
		||||
            temp_idx = *static_cast<int *>(RTA_DATA(attr));
 | 
			
		||||
            break;
 | 
			
		||||
          case RTA_PRIORITY:
 | 
			
		||||
            priority = *(uint32_t *)RTA_DATA(attr);
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Check if we have a default route.
 | 
			
		||||
      if (has_gateway && !has_destination && temp_idx != -1) {
 | 
			
		||||
        // Check if this is the first default route we see, or if this new
 | 
			
		||||
        // route have a higher priority.
 | 
			
		||||
        if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority))) {
 | 
			
		||||
          // Clear if's state for the case were there is a higher priority
 | 
			
		||||
          // route on a different interface.
 | 
			
		||||
          net->clearIface();
 | 
			
		||||
          net->ifid_ = temp_idx;
 | 
			
		||||
          net->route_priority = priority;
 | 
			
		||||
          net->gwaddr_ = temp_gw_addr;
 | 
			
		||||
          spdlog::debug("network: new default route via {} on if{} metric {}", temp_gw_addr,
 | 
			
		||||
                        temp_idx, priority);
 | 
			
		||||
 | 
			
		||||
          /* Ask ifname associated with temp_idx as well as carrier status */
 | 
			
		||||
          struct ifinfomsg ifinfo_hdr = {
 | 
			
		||||
              .ifi_family = AF_UNSPEC,
 | 
			
		||||
              .ifi_index = temp_idx,
 | 
			
		||||
          };
 | 
			
		||||
          int err;
 | 
			
		||||
          err = nl_send_simple(net->ev_sock_, RTM_GETLINK, NLM_F_REQUEST, &ifinfo_hdr,
 | 
			
		||||
                               sizeof(ifinfo_hdr));
 | 
			
		||||
          if (err < 0) {
 | 
			
		||||
            spdlog::error("network: failed to ask link info: {}", err);
 | 
			
		||||
            /* Ask for a dump of all links instead */
 | 
			
		||||
            net->want_link_dump_ = true;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          /* Also ask for the address. Asking for a addresses of a specific
 | 
			
		||||
           * interface doesn't seems to work so ask for a dump of all
 | 
			
		||||
           * addresses. */
 | 
			
		||||
          net->want_addr_dump_ = true;
 | 
			
		||||
          net->askForStateDump();
 | 
			
		||||
          net->thread_timer_.wake_up();
 | 
			
		||||
        } else if (is_del_event && temp_idx == net->ifid_ && net->route_priority == priority) {
 | 
			
		||||
          spdlog::debug("network: default route deleted {}/if{} metric {}", net->ifname_, temp_idx,
 | 
			
		||||
                        priority);
 | 
			
		||||
 | 
			
		||||
          net->clearIface();
 | 
			
		||||
          net->dp.emit();
 | 
			
		||||
          /* Ask for a dump of all routes in case another one is already
 | 
			
		||||
           * setup. If there's none, there'll be an event with new one
 | 
			
		||||
           * later. */
 | 
			
		||||
          net->want_route_dump_ = true;
 | 
			
		||||
          net->askForStateDump();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return NL_OK;
 | 
			
		||||
@@ -702,30 +687,26 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
 | 
			
		||||
void waybar::modules::Network::askForStateDump(void) {
 | 
			
		||||
  /* We need to wait until the current dump is done before sending new
 | 
			
		||||
   * messages. handleEventsDone() is called when a dump is done. */
 | 
			
		||||
  if (dump_in_progress_)
 | 
			
		||||
    return;
 | 
			
		||||
  if (dump_in_progress_) return;
 | 
			
		||||
 | 
			
		||||
  struct rtgenmsg rt_hdr = {
 | 
			
		||||
    .rtgen_family = AF_UNSPEC,
 | 
			
		||||
      .rtgen_family = AF_UNSPEC,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (want_route_dump_) {
 | 
			
		||||
    rt_hdr.rtgen_family = family_;
 | 
			
		||||
    nl_send_simple(ev_sock_, RTM_GETROUTE, NLM_F_DUMP,
 | 
			
		||||
                   &rt_hdr, sizeof (rt_hdr));
 | 
			
		||||
    nl_send_simple(ev_sock_, RTM_GETROUTE, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
 | 
			
		||||
    want_route_dump_ = false;
 | 
			
		||||
    dump_in_progress_ = true;
 | 
			
		||||
 | 
			
		||||
  } else if (want_link_dump_) {
 | 
			
		||||
    nl_send_simple(ev_sock_, RTM_GETLINK, NLM_F_DUMP,
 | 
			
		||||
                   &rt_hdr, sizeof (rt_hdr));
 | 
			
		||||
    nl_send_simple(ev_sock_, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
 | 
			
		||||
    want_link_dump_ = false;
 | 
			
		||||
    dump_in_progress_ = true;
 | 
			
		||||
 | 
			
		||||
  } else if (want_addr_dump_) {
 | 
			
		||||
    rt_hdr.rtgen_family = family_;
 | 
			
		||||
    nl_send_simple(ev_sock_, RTM_GETADDR, NLM_F_DUMP,
 | 
			
		||||
                   &rt_hdr, sizeof (rt_hdr));
 | 
			
		||||
    nl_send_simple(ev_sock_, RTM_GETADDR, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
 | 
			
		||||
    want_addr_dump_ = false;
 | 
			
		||||
    dump_in_progress_ = true;
 | 
			
		||||
  }
 | 
			
		||||
@@ -739,10 +720,10 @@ int waybar::modules::Network::handleEventsDone(struct nl_msg *msg, void *data) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
 | 
			
		||||
  auto              net = static_cast<waybar::modules::Network *>(data);
 | 
			
		||||
  auto              gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
 | 
			
		||||
  struct nlattr *   tb[NL80211_ATTR_MAX + 1];
 | 
			
		||||
  struct nlattr *   bss[NL80211_BSS_MAX + 1];
 | 
			
		||||
  auto net = static_cast<waybar::modules::Network *>(data);
 | 
			
		||||
  auto gnlh = static_cast<genlmsghdr *>(nlmsg_data(nlmsg_hdr(msg)));
 | 
			
		||||
  struct nlattr *tb[NL80211_ATTR_MAX + 1];
 | 
			
		||||
  struct nlattr *bss[NL80211_BSS_MAX + 1];
 | 
			
		||||
  struct nla_policy bss_policy[NL80211_BSS_MAX + 1]{};
 | 
			
		||||
  bss_policy[NL80211_BSS_TSF].type = NLA_U64;
 | 
			
		||||
  bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32;
 | 
			
		||||
@@ -754,8 +735,8 @@ int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
 | 
			
		||||
  bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
 | 
			
		||||
  bss_policy[NL80211_BSS_STATUS].type = NLA_U32;
 | 
			
		||||
 | 
			
		||||
  if (nla_parse(
 | 
			
		||||
          tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), nullptr) < 0) {
 | 
			
		||||
  if (nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0),
 | 
			
		||||
                nullptr) < 0) {
 | 
			
		||||
    return NL_SKIP;
 | 
			
		||||
  }
 | 
			
		||||
  if (tb[NL80211_ATTR_BSS] == nullptr) {
 | 
			
		||||
@@ -775,16 +756,16 @@ int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
 | 
			
		||||
 | 
			
		||||
void waybar::modules::Network::parseEssid(struct nlattr **bss) {
 | 
			
		||||
  if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) {
 | 
			
		||||
    auto       ies = static_cast<char *>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
 | 
			
		||||
    auto       ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
 | 
			
		||||
    auto ies = static_cast<char *>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
 | 
			
		||||
    auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
 | 
			
		||||
    const auto hdr_len = 2;
 | 
			
		||||
    while (ies_len > hdr_len && ies[0] != 0) {
 | 
			
		||||
      ies_len -= ies[1] + hdr_len;
 | 
			
		||||
      ies += ies[1] + hdr_len;
 | 
			
		||||
    }
 | 
			
		||||
    if (ies_len > hdr_len && ies_len > ies[1] + hdr_len) {
 | 
			
		||||
      auto        essid_begin = ies + hdr_len;
 | 
			
		||||
      auto        essid_end = essid_begin + ies[1];
 | 
			
		||||
      auto essid_begin = ies + hdr_len;
 | 
			
		||||
      auto essid_end = essid_begin + ies[1];
 | 
			
		||||
      std::string essid_raw;
 | 
			
		||||
      std::copy(essid_begin, essid_end, std::back_inserter(essid_raw));
 | 
			
		||||
      essid_ = Glib::Markup::escape_text(essid_raw);
 | 
			
		||||
@@ -804,8 +785,10 @@ void waybar::modules::Network::parseSignal(struct nlattr **bss) {
 | 
			
		||||
    const int hardwareOptimum = -45;
 | 
			
		||||
    const int hardwareMin = -90;
 | 
			
		||||
    const int strength =
 | 
			
		||||
        100 - ((abs(signal_strength_dbm_ - hardwareOptimum) / double{hardwareOptimum - hardwareMin}) * 100);
 | 
			
		||||
    signal_strength_ = std::clamp(strength, 0, 100);  
 | 
			
		||||
        100 -
 | 
			
		||||
        ((abs(signal_strength_dbm_ - hardwareOptimum) / double{hardwareOptimum - hardwareMin}) *
 | 
			
		||||
         100);
 | 
			
		||||
    signal_strength_ = std::clamp(strength, 0, 100);
 | 
			
		||||
 | 
			
		||||
    if (signal_strength_dbm_ >= -50) {
 | 
			
		||||
      signal_strength_app_ = "Great Connectivity";
 | 
			
		||||
@@ -829,7 +812,7 @@ void waybar::modules::Network::parseSignal(struct nlattr **bss) {
 | 
			
		||||
void waybar::modules::Network::parseFreq(struct nlattr **bss) {
 | 
			
		||||
  if (bss[NL80211_BSS_FREQUENCY] != nullptr) {
 | 
			
		||||
    // in GHz
 | 
			
		||||
    frequency_ = (double) nla_get_u32(bss[NL80211_BSS_FREQUENCY]) / 1000;
 | 
			
		||||
    frequency_ = (double)nla_get_u32(bss[NL80211_BSS_FREQUENCY]) / 1000;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -853,9 +836,8 @@ auto waybar::modules::Network::getInfo() -> void {
 | 
			
		||||
  if (nl_msg == nullptr) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (genlmsg_put(
 | 
			
		||||
          nl_msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl80211_id_, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) ==
 | 
			
		||||
          nullptr ||
 | 
			
		||||
  if (genlmsg_put(nl_msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl80211_id_, 0, NLM_F_DUMP,
 | 
			
		||||
                  NL80211_CMD_GET_SCAN, 0) == nullptr ||
 | 
			
		||||
      nla_put_u32(nl_msg, NL80211_ATTR_IFINDEX, ifid_) < 0) {
 | 
			
		||||
    nlmsg_free(nl_msg);
 | 
			
		||||
    return;
 | 
			
		||||
 
 | 
			
		||||
@@ -50,15 +50,14 @@ void waybar::modules::Pulseaudio::contextStateCb(pa_context *c, void *data) {
 | 
			
		||||
    case PA_CONTEXT_READY:
 | 
			
		||||
      pa_context_get_server_info(c, serverInfoCb, data);
 | 
			
		||||
      pa_context_set_subscribe_callback(c, subscribeCb, data);
 | 
			
		||||
      pa_context_subscribe(
 | 
			
		||||
          c,
 | 
			
		||||
          static_cast<enum pa_subscription_mask>(static_cast<int>(PA_SUBSCRIPTION_MASK_SERVER) |
 | 
			
		||||
                                                 static_cast<int>(PA_SUBSCRIPTION_MASK_SINK) |
 | 
			
		||||
                                                 static_cast<int>(PA_SUBSCRIPTION_MASK_SINK_INPUT) |
 | 
			
		||||
                                                 static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE) |
 | 
			
		||||
                                                 static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)),
 | 
			
		||||
          nullptr,
 | 
			
		||||
          nullptr);
 | 
			
		||||
      pa_context_subscribe(c,
 | 
			
		||||
                           static_cast<enum pa_subscription_mask>(
 | 
			
		||||
                               static_cast<int>(PA_SUBSCRIPTION_MASK_SERVER) |
 | 
			
		||||
                               static_cast<int>(PA_SUBSCRIPTION_MASK_SINK) |
 | 
			
		||||
                               static_cast<int>(PA_SUBSCRIPTION_MASK_SINK_INPUT) |
 | 
			
		||||
                               static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE) |
 | 
			
		||||
                               static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT)),
 | 
			
		||||
                           nullptr, nullptr);
 | 
			
		||||
      break;
 | 
			
		||||
    case PA_CONTEXT_FAILED:
 | 
			
		||||
      pa->mainloop_api_->quit(pa->mainloop_api_, 1);
 | 
			
		||||
@@ -81,16 +80,16 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
  if (dir == SCROLL_DIR::NONE) {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  if (config_["reverse-scrolling"].asInt() == 1){
 | 
			
		||||
  if (config_["reverse-scrolling"].asInt() == 1) {
 | 
			
		||||
    if (dir == SCROLL_DIR::UP) {
 | 
			
		||||
      dir = SCROLL_DIR::DOWN;
 | 
			
		||||
    } else if (dir == SCROLL_DIR::DOWN) {
 | 
			
		||||
      dir = SCROLL_DIR::UP;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  double      volume_tick = static_cast<double>(PA_VOLUME_NORM) / 100;
 | 
			
		||||
  double volume_tick = static_cast<double>(PA_VOLUME_NORM) / 100;
 | 
			
		||||
  pa_volume_t change = volume_tick;
 | 
			
		||||
  pa_cvolume  pa_volume = pa_volume_;
 | 
			
		||||
  pa_cvolume pa_volume = pa_volume_;
 | 
			
		||||
  // isDouble returns true for integers as well, just in case
 | 
			
		||||
  if (config_["scroll-step"].isDouble()) {
 | 
			
		||||
    change = round(config_["scroll-step"].asDouble() * volume_tick);
 | 
			
		||||
@@ -111,7 +110,7 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
/*
 | 
			
		||||
 * Called when an event we subscribed to occurs.
 | 
			
		||||
 */
 | 
			
		||||
void waybar::modules::Pulseaudio::subscribeCb(pa_context *                 context,
 | 
			
		||||
void waybar::modules::Pulseaudio::subscribeCb(pa_context *context,
 | 
			
		||||
                                              pa_subscription_event_type_t type, uint32_t idx,
 | 
			
		||||
                                              void *data) {
 | 
			
		||||
  unsigned facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
 | 
			
		||||
@@ -164,8 +163,7 @@ void waybar::modules::Pulseaudio::sourceInfoCb(pa_context * /*context*/, const p
 | 
			
		||||
 */
 | 
			
		||||
void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_sink_info *i,
 | 
			
		||||
                                             int /*eol*/, void *data) {
 | 
			
		||||
  if (i == nullptr)
 | 
			
		||||
    return;
 | 
			
		||||
  if (i == nullptr) return;
 | 
			
		||||
 | 
			
		||||
  auto pa = static_cast<waybar::modules::Pulseaudio *>(data);
 | 
			
		||||
  if (pa->current_sink_name_ == i->name) {
 | 
			
		||||
@@ -212,15 +210,7 @@ void waybar::modules::Pulseaudio::serverInfoCb(pa_context *context, const pa_ser
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const std::array<std::string, 9> ports = {
 | 
			
		||||
    "headphone",
 | 
			
		||||
    "speaker",
 | 
			
		||||
    "hdmi",
 | 
			
		||||
    "headset",
 | 
			
		||||
    "hands-free",
 | 
			
		||||
    "portable",
 | 
			
		||||
    "car",
 | 
			
		||||
    "hifi",
 | 
			
		||||
    "phone",
 | 
			
		||||
    "headphone", "speaker", "hdmi", "headset", "hands-free", "portable", "car", "hifi", "phone",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const std::vector<std::string> waybar::modules::Pulseaudio::getPulseIcon() const {
 | 
			
		||||
@@ -238,11 +228,11 @@ const std::vector<std::string> waybar::modules::Pulseaudio::getPulseIcon() const
 | 
			
		||||
 | 
			
		||||
auto waybar::modules::Pulseaudio::update() -> void {
 | 
			
		||||
  auto format = format_;
 | 
			
		||||
  std::string                 tooltip_format;
 | 
			
		||||
  std::string tooltip_format;
 | 
			
		||||
  if (!alt_) {
 | 
			
		||||
    std::string format_name = "format";
 | 
			
		||||
    if (monitor_.find("a2dp_sink") != std::string::npos || // PulseAudio
 | 
			
		||||
        monitor_.find("a2dp-sink") != std::string::npos) { // PipeWire
 | 
			
		||||
    if (monitor_.find("a2dp_sink") != std::string::npos ||  // PulseAudio
 | 
			
		||||
        monitor_.find("a2dp-sink") != std::string::npos) {  // PipeWire
 | 
			
		||||
      format_name = format_name + "-bluetooth";
 | 
			
		||||
      label_.get_style_context()->add_class("bluetooth");
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -260,8 +250,7 @@ auto waybar::modules::Pulseaudio::update() -> void {
 | 
			
		||||
      label_.get_style_context()->remove_class("muted");
 | 
			
		||||
      label_.get_style_context()->remove_class("sink-muted");
 | 
			
		||||
    }
 | 
			
		||||
    format =
 | 
			
		||||
      config_[format_name].isString() ? config_[format_name].asString() : format;
 | 
			
		||||
    format = config_[format_name].isString() ? config_[format_name].asString() : format;
 | 
			
		||||
  }
 | 
			
		||||
  // TODO: find a better way to split source/sink
 | 
			
		||||
  std::string format_source = "{volume}%";
 | 
			
		||||
@@ -277,13 +266,10 @@ auto waybar::modules::Pulseaudio::update() -> void {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  format_source = fmt::format(format_source, fmt::arg("volume", source_volume_));
 | 
			
		||||
  label_.set_markup(fmt::format(format,
 | 
			
		||||
                                fmt::arg("desc", desc_),
 | 
			
		||||
                                fmt::arg("volume", volume_),
 | 
			
		||||
                                fmt::arg("format_source", format_source),
 | 
			
		||||
                                fmt::arg("source_volume", source_volume_),
 | 
			
		||||
                                fmt::arg("source_desc", source_desc_),
 | 
			
		||||
                                fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
 | 
			
		||||
  label_.set_markup(fmt::format(
 | 
			
		||||
      format, fmt::arg("desc", desc_), fmt::arg("volume", volume_),
 | 
			
		||||
      fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_),
 | 
			
		||||
      fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
 | 
			
		||||
  getState(volume_);
 | 
			
		||||
 | 
			
		||||
  if (tooltipEnabled()) {
 | 
			
		||||
@@ -292,13 +278,10 @@ auto waybar::modules::Pulseaudio::update() -> void {
 | 
			
		||||
    }
 | 
			
		||||
    if (!tooltip_format.empty()) {
 | 
			
		||||
      label_.set_tooltip_text(fmt::format(
 | 
			
		||||
        tooltip_format,
 | 
			
		||||
        fmt::arg("desc", desc_),
 | 
			
		||||
        fmt::arg("volume", volume_),
 | 
			
		||||
        fmt::arg("format_source", format_source),
 | 
			
		||||
        fmt::arg("source_volume", source_volume_),
 | 
			
		||||
        fmt::arg("source_desc", source_desc_),
 | 
			
		||||
        fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
 | 
			
		||||
          tooltip_format, fmt::arg("desc", desc_), fmt::arg("volume", volume_),
 | 
			
		||||
          fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_),
 | 
			
		||||
          fmt::arg("source_desc", source_desc_),
 | 
			
		||||
          fmt::arg("icon", getIcon(volume_, getPulseIcon()))));
 | 
			
		||||
    } else {
 | 
			
		||||
      label_.set_tooltip_text(desc_);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
#include "modules/river/tags.hpp"
 | 
			
		||||
 | 
			
		||||
#include <gtkmm/button.h>
 | 
			
		||||
#include <gtkmm/label.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
@@ -6,7 +8,6 @@
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#include "client.hpp"
 | 
			
		||||
#include "modules/river/tags.hpp"
 | 
			
		||||
#include "xdg-output-unstable-v1-client-protocol.h"
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules::river {
 | 
			
		||||
@@ -44,7 +45,7 @@ static void listen_command_failure(void *data,
 | 
			
		||||
  spdlog::error("failure when selecting/toggling tags {}", output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const zriver_command_callback_v1_listener command_callback_listener_impl {
 | 
			
		||||
static const zriver_command_callback_v1_listener command_callback_listener_impl{
 | 
			
		||||
    .success = listen_command_success,
 | 
			
		||||
    .failure = listen_command_failure,
 | 
			
		||||
};
 | 
			
		||||
@@ -77,7 +78,6 @@ static void handle_global_remove(void *data, struct wl_registry *registry, uint3
 | 
			
		||||
  /* Ignore event */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const wl_registry_listener registry_listener_impl = {.global = handle_global,
 | 
			
		||||
                                                            .global_remove = handle_global_remove};
 | 
			
		||||
 | 
			
		||||
@@ -89,7 +89,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
 | 
			
		||||
      bar_(bar),
 | 
			
		||||
      box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0},
 | 
			
		||||
      output_status_{nullptr} {
 | 
			
		||||
  struct wl_display * display = Client::inst()->wl_display;
 | 
			
		||||
  struct wl_display *display = Client::inst()->wl_display;
 | 
			
		||||
  struct wl_registry *registry = wl_display_get_registry(display);
 | 
			
		||||
  wl_registry_add_listener(registry, ®istry_listener_impl, this);
 | 
			
		||||
  wl_display_roundtrip(display);
 | 
			
		||||
@@ -119,7 +119,7 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
 | 
			
		||||
 | 
			
		||||
  std::vector<std::string> tag_labels(num_tags);
 | 
			
		||||
  for (uint32_t tag = 0; tag < num_tags; ++tag) {
 | 
			
		||||
    tag_labels[tag] = std::to_string(tag+1);
 | 
			
		||||
    tag_labels[tag] = std::to_string(tag + 1);
 | 
			
		||||
  }
 | 
			
		||||
  const Json::Value custom_labels = config["tag-labels"];
 | 
			
		||||
  if (custom_labels.isArray() && !custom_labels.empty()) {
 | 
			
		||||
@@ -134,8 +134,10 @@ Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &con
 | 
			
		||||
    button.set_relief(Gtk::RELIEF_NONE);
 | 
			
		||||
    box_.pack_start(button, false, false, 0);
 | 
			
		||||
    if (!config_["disable-click"].asBool()) {
 | 
			
		||||
      button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), i));
 | 
			
		||||
      button.signal_button_press_event().connect(sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), i));
 | 
			
		||||
      button.signal_clicked().connect(
 | 
			
		||||
          sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), i));
 | 
			
		||||
      button.signal_button_press_event().connect(
 | 
			
		||||
          sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), i));
 | 
			
		||||
    }
 | 
			
		||||
    button.show();
 | 
			
		||||
    i <<= 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/simpleclock.hpp"
 | 
			
		||||
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
 | 
			
		||||
@@ -13,7 +14,7 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto waybar::modules::Clock::update() -> void {
 | 
			
		||||
  tzset(); // Update timezone information
 | 
			
		||||
  tzset();  // Update timezone information
 | 
			
		||||
  auto now = std::chrono::system_clock::now();
 | 
			
		||||
  auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
 | 
			
		||||
  auto text = fmt::format(format_, localtime);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,16 @@
 | 
			
		||||
#include "modules/sndio.hpp"
 | 
			
		||||
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules {
 | 
			
		||||
 | 
			
		||||
void ondesc(void *arg, struct sioctl_desc *d, int curval) {
 | 
			
		||||
  auto self = static_cast<Sndio*>(arg);
 | 
			
		||||
  auto self = static_cast<Sndio *>(arg);
 | 
			
		||||
  if (d == NULL) {
 | 
			
		||||
    // d is NULL when the list is done
 | 
			
		||||
    return;
 | 
			
		||||
@@ -17,7 +19,7 @@ void ondesc(void *arg, struct sioctl_desc *d, int curval) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void onval(void *arg, unsigned int addr, unsigned int val) {
 | 
			
		||||
  auto self = static_cast<Sndio*>(arg);
 | 
			
		||||
  auto self = static_cast<Sndio *>(arg);
 | 
			
		||||
  self->put_val(addr, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -52,10 +54,8 @@ Sndio::Sndio(const std::string &id, const Json::Value &config)
 | 
			
		||||
  event_box_.show();
 | 
			
		||||
 | 
			
		||||
  event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK | Gdk::BUTTON_PRESS_MASK);
 | 
			
		||||
  event_box_.signal_scroll_event().connect(
 | 
			
		||||
    sigc::mem_fun(*this, &Sndio::handleScroll));
 | 
			
		||||
  event_box_.signal_button_press_event().connect(
 | 
			
		||||
    sigc::mem_fun(*this, &Sndio::handleToggle));
 | 
			
		||||
  event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Sndio::handleScroll));
 | 
			
		||||
  event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &Sndio::handleToggle));
 | 
			
		||||
 | 
			
		||||
  thread_ = [this] {
 | 
			
		||||
    dp.emit();
 | 
			
		||||
@@ -80,7 +80,7 @@ Sndio::Sndio(const std::string &id, const Json::Value &config)
 | 
			
		||||
      while (thread_.isRunning()) {
 | 
			
		||||
        try {
 | 
			
		||||
          connect_to_sndio();
 | 
			
		||||
        } catch(std::runtime_error const& e) {
 | 
			
		||||
        } catch (std::runtime_error const &e) {
 | 
			
		||||
          // avoid leaking hdl_
 | 
			
		||||
          if (hdl_) {
 | 
			
		||||
            sioctl_close(hdl_);
 | 
			
		||||
@@ -98,9 +98,7 @@ Sndio::Sndio(const std::string &id, const Json::Value &config)
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Sndio::~Sndio() {
 | 
			
		||||
  sioctl_close(hdl_);
 | 
			
		||||
}
 | 
			
		||||
Sndio::~Sndio() { sioctl_close(hdl_); }
 | 
			
		||||
 | 
			
		||||
auto Sndio::update() -> void {
 | 
			
		||||
  auto format = format_;
 | 
			
		||||
@@ -112,9 +110,7 @@ auto Sndio::update() -> void {
 | 
			
		||||
    label_.get_style_context()->remove_class("muted");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  label_.set_markup(fmt::format(format,
 | 
			
		||||
                                fmt::arg("volume", vol),
 | 
			
		||||
                                fmt::arg("raw_value", volume_)));
 | 
			
		||||
  label_.set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_)));
 | 
			
		||||
 | 
			
		||||
  ALabel::update();
 | 
			
		||||
}
 | 
			
		||||
@@ -177,7 +173,7 @@ bool Sndio::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Sndio::handleToggle(GdkEventButton* const& e) {
 | 
			
		||||
bool Sndio::handleToggle(GdkEventButton *const &e) {
 | 
			
		||||
  // toggle mute only when no user provided events are configured
 | 
			
		||||
  if (config_["on-click"].isString()) {
 | 
			
		||||
    return AModule::handleToggle(e);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/sni/host.hpp"
 | 
			
		||||
 | 
			
		||||
#include <fmt/ostream.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
@@ -32,8 +33,7 @@ Host::~Host() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Host::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
 | 
			
		||||
  watcher_id_ = Gio::DBus::watch_name(conn,
 | 
			
		||||
                                      "org.kde.StatusNotifierWatcher",
 | 
			
		||||
  watcher_id_ = Gio::DBus::watch_name(conn, "org.kde.StatusNotifierWatcher",
 | 
			
		||||
                                      sigc::mem_fun(*this, &Host::nameAppeared),
 | 
			
		||||
                                      sigc::mem_fun(*this, &Host::nameVanished));
 | 
			
		||||
}
 | 
			
		||||
@@ -45,13 +45,8 @@ void Host::nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>& conn, const G
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  cancellable_ = g_cancellable_new();
 | 
			
		||||
  sn_watcher_proxy_new(conn->gobj(),
 | 
			
		||||
                       G_DBUS_PROXY_FLAGS_NONE,
 | 
			
		||||
                       "org.kde.StatusNotifierWatcher",
 | 
			
		||||
                       "/StatusNotifierWatcher",
 | 
			
		||||
                       cancellable_,
 | 
			
		||||
                       &Host::proxyReady,
 | 
			
		||||
                       this);
 | 
			
		||||
  sn_watcher_proxy_new(conn->gobj(), G_DBUS_PROXY_FLAGS_NONE, "org.kde.StatusNotifierWatcher",
 | 
			
		||||
                       "/StatusNotifierWatcher", cancellable_, &Host::proxyReady, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const Glib::ustring name) {
 | 
			
		||||
@@ -62,7 +57,7 @@ void Host::nameVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn, const G
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
 | 
			
		||||
  GError*    error = nullptr;
 | 
			
		||||
  GError* error = nullptr;
 | 
			
		||||
  SnWatcher* watcher = sn_watcher_proxy_new_finish(res, &error);
 | 
			
		||||
  if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 | 
			
		||||
    spdlog::error("Host: {}", error->message);
 | 
			
		||||
@@ -76,8 +71,8 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
 | 
			
		||||
    g_error_free(error);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  sn_watcher_call_register_host(
 | 
			
		||||
      host->watcher_, host->object_path_.c_str(), host->cancellable_, &Host::registerHost, data);
 | 
			
		||||
  sn_watcher_call_register_host(host->watcher_, host->object_path_.c_str(), host->cancellable_,
 | 
			
		||||
                                &Host::registerHost, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ struct fmt::formatter<Glib::VariantBase> : formatter<std::string> {
 | 
			
		||||
namespace waybar::modules::SNI {
 | 
			
		||||
 | 
			
		||||
static const Glib::ustring SNI_INTERFACE_NAME = sn_item_interface_info()->name;
 | 
			
		||||
static const unsigned      UPDATE_DEBOUNCE_TIME = 10;
 | 
			
		||||
static const unsigned UPDATE_DEBOUNCE_TIME = 10;
 | 
			
		||||
 | 
			
		||||
Item::Item(const std::string& bn, const std::string& op, const Json::Value& config, const Bar& bar)
 | 
			
		||||
    : bus_name(bn),
 | 
			
		||||
@@ -49,7 +49,7 @@ Item::Item(const std::string& bn, const std::string& op, const Json::Value& conf
 | 
			
		||||
    show_passive_ = config["show-passive-items"].asBool();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto &window = const_cast<Bar &>(bar).window;
 | 
			
		||||
  auto& window = const_cast<Bar&>(bar).window;
 | 
			
		||||
  window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Item::onConfigure));
 | 
			
		||||
  event_box.add(image);
 | 
			
		||||
  event_box.add_events(Gdk::BUTTON_PRESS_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
 | 
			
		||||
@@ -62,18 +62,12 @@ Item::Item(const std::string& bn, const std::string& op, const Json::Value& conf
 | 
			
		||||
  cancellable_ = Gio::Cancellable::create();
 | 
			
		||||
 | 
			
		||||
  auto interface = Glib::wrap(sn_item_interface_info(), true);
 | 
			
		||||
  Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::BUS_TYPE_SESSION,
 | 
			
		||||
                                   bus_name,
 | 
			
		||||
                                   object_path,
 | 
			
		||||
                                   SNI_INTERFACE_NAME,
 | 
			
		||||
                                   sigc::mem_fun(*this, &Item::proxyReady),
 | 
			
		||||
                                   cancellable_,
 | 
			
		||||
                                   interface);
 | 
			
		||||
  Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::BUS_TYPE_SESSION, bus_name, object_path,
 | 
			
		||||
                                   SNI_INTERFACE_NAME, sigc::mem_fun(*this, &Item::proxyReady),
 | 
			
		||||
                                   cancellable_, interface);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Item::onConfigure(GdkEventConfigure* ev) {
 | 
			
		||||
  this->updateImage();
 | 
			
		||||
}
 | 
			
		||||
void Item::onConfigure(GdkEventConfigure* ev) { this->updateImage(); }
 | 
			
		||||
 | 
			
		||||
void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
 | 
			
		||||
  try {
 | 
			
		||||
@@ -167,16 +161,10 @@ void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
 | 
			
		||||
    }
 | 
			
		||||
  } catch (const Glib::Error& err) {
 | 
			
		||||
    spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
 | 
			
		||||
                 id.empty() ? bus_name : id,
 | 
			
		||||
                 name,
 | 
			
		||||
                 value,
 | 
			
		||||
                 err.what());
 | 
			
		||||
                 id.empty() ? bus_name : id, name, value, err.what());
 | 
			
		||||
  } catch (const std::exception& err) {
 | 
			
		||||
    spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
 | 
			
		||||
                 id.empty() ? bus_name : id,
 | 
			
		||||
                 name,
 | 
			
		||||
                 value,
 | 
			
		||||
                 err.what());
 | 
			
		||||
                 id.empty() ? bus_name : id, name, value, err.what());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -199,8 +187,7 @@ void Item::getUpdatedProperties() {
 | 
			
		||||
  auto params = Glib::VariantContainerBase::create_tuple(
 | 
			
		||||
      {Glib::Variant<Glib::ustring>::create(SNI_INTERFACE_NAME)});
 | 
			
		||||
  proxy_->call("org.freedesktop.DBus.Properties.GetAll",
 | 
			
		||||
               sigc::mem_fun(*this, &Item::processUpdatedProperties),
 | 
			
		||||
               params);
 | 
			
		||||
               sigc::mem_fun(*this, &Item::processUpdatedProperties), params);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
 | 
			
		||||
@@ -266,11 +253,11 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
 | 
			
		||||
    return Glib::RefPtr<Gdk::Pixbuf>{};
 | 
			
		||||
  }
 | 
			
		||||
  GVariant* val;
 | 
			
		||||
  gint      lwidth = 0;
 | 
			
		||||
  gint      lheight = 0;
 | 
			
		||||
  gint      width;
 | 
			
		||||
  gint      height;
 | 
			
		||||
  guchar*   array = nullptr;
 | 
			
		||||
  gint lwidth = 0;
 | 
			
		||||
  gint lheight = 0;
 | 
			
		||||
  gint width;
 | 
			
		||||
  gint height;
 | 
			
		||||
  guchar* array = nullptr;
 | 
			
		||||
  while (g_variant_iter_loop(it, "(ii@ay)", &width, &height, &val)) {
 | 
			
		||||
    if (width > 0 && height > 0 && val != nullptr && width * height > lwidth * lheight) {
 | 
			
		||||
      auto size = g_variant_get_size(val);
 | 
			
		||||
@@ -303,14 +290,8 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
 | 
			
		||||
      array[i + 2] = array[i + 3];
 | 
			
		||||
      array[i + 3] = alpha;
 | 
			
		||||
    }
 | 
			
		||||
    return Gdk::Pixbuf::create_from_data(array,
 | 
			
		||||
                                         Gdk::Colorspace::COLORSPACE_RGB,
 | 
			
		||||
                                         true,
 | 
			
		||||
                                         8,
 | 
			
		||||
                                         lwidth,
 | 
			
		||||
                                         lheight,
 | 
			
		||||
                                         4 * lwidth,
 | 
			
		||||
                                         &pixbuf_data_deleter);
 | 
			
		||||
    return Gdk::Pixbuf::create_from_data(array, Gdk::Colorspace::COLORSPACE_RGB, true, 8, lwidth,
 | 
			
		||||
                                         lheight, 4 * lwidth, &pixbuf_data_deleter);
 | 
			
		||||
  }
 | 
			
		||||
  return Glib::RefPtr<Gdk::Pixbuf>{};
 | 
			
		||||
}
 | 
			
		||||
@@ -318,7 +299,7 @@ Glib::RefPtr<Gdk::Pixbuf> Item::extractPixBuf(GVariant* variant) {
 | 
			
		||||
void Item::updateImage() {
 | 
			
		||||
  auto pixbuf = getIconPixbuf();
 | 
			
		||||
  auto scaled_icon_size = getScaledIconSize();
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
  if (!pixbuf) {
 | 
			
		||||
    pixbuf = getIconByName("image-missing", getScaledIconSize());
 | 
			
		||||
  }
 | 
			
		||||
@@ -349,7 +330,7 @@ Glib::RefPtr<Gdk::Pixbuf> Item::getIconPixbuf() {
 | 
			
		||||
    }
 | 
			
		||||
  } catch (Glib::Error& e) {
 | 
			
		||||
    spdlog::error("Item '{}': {}", id, static_cast<std::string>(e.what()));
 | 
			
		||||
  } 
 | 
			
		||||
  }
 | 
			
		||||
  return getIconByName("image-missing", getScaledIconSize());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -374,15 +355,15 @@ Glib::RefPtr<Gdk::Pixbuf> Item::getIconByName(const std::string& name, int reque
 | 
			
		||||
    tmp_size = request_size;
 | 
			
		||||
  }
 | 
			
		||||
  if (!icon_theme_path.empty() &&
 | 
			
		||||
      icon_theme->lookup_icon(
 | 
			
		||||
          name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE)) {
 | 
			
		||||
    return icon_theme->load_icon(
 | 
			
		||||
        name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
 | 
			
		||||
      icon_theme->lookup_icon(name.c_str(), tmp_size,
 | 
			
		||||
                              Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE)) {
 | 
			
		||||
    return icon_theme->load_icon(name.c_str(), tmp_size,
 | 
			
		||||
                                 Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
 | 
			
		||||
  }
 | 
			
		||||
  Glib::RefPtr<Gtk::IconTheme> default_theme = Gtk::IconTheme::get_default();
 | 
			
		||||
  default_theme->rescan_if_needed();
 | 
			
		||||
  return default_theme->load_icon(
 | 
			
		||||
      name.c_str(), tmp_size, Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
 | 
			
		||||
  return default_theme->load_icon(name.c_str(), tmp_size,
 | 
			
		||||
                                  Gtk::IconLookupFlags::ICON_LOOKUP_FORCE_SIZE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double Item::getScaledIconSize() {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/sni/tray.hpp"
 | 
			
		||||
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules::SNI {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/sni/watcher.hpp"
 | 
			
		||||
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
using namespace waybar::modules::SNI;
 | 
			
		||||
@@ -29,8 +30,8 @@ Watcher::~Watcher() {
 | 
			
		||||
 | 
			
		||||
void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
 | 
			
		||||
  GError* error = nullptr;
 | 
			
		||||
  g_dbus_interface_skeleton_export(
 | 
			
		||||
      G_DBUS_INTERFACE_SKELETON(watcher_), conn->gobj(), "/StatusNotifierWatcher", &error);
 | 
			
		||||
  g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(watcher_), conn->gobj(),
 | 
			
		||||
                                   "/StatusNotifierWatcher", &error);
 | 
			
		||||
  if (error != nullptr) {
 | 
			
		||||
    // Don't print an error when a watcher is already present
 | 
			
		||||
    if (error->code != 2) {
 | 
			
		||||
@@ -39,10 +40,10 @@ void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib:
 | 
			
		||||
    g_error_free(error);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  g_signal_connect_swapped(
 | 
			
		||||
      watcher_, "handle-register-item", G_CALLBACK(&Watcher::handleRegisterItem), this);
 | 
			
		||||
  g_signal_connect_swapped(
 | 
			
		||||
      watcher_, "handle-register-host", G_CALLBACK(&Watcher::handleRegisterHost), this);
 | 
			
		||||
  g_signal_connect_swapped(watcher_, "handle-register-item",
 | 
			
		||||
                           G_CALLBACK(&Watcher::handleRegisterItem), this);
 | 
			
		||||
  g_signal_connect_swapped(watcher_, "handle-register-host",
 | 
			
		||||
                           G_CALLBACK(&Watcher::handleRegisterHost), this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean Watcher::handleRegisterHost(Watcher* obj, GDBusMethodInvocation* invocation,
 | 
			
		||||
@@ -55,22 +56,16 @@ gboolean Watcher::handleRegisterHost(Watcher* obj, GDBusMethodInvocation* invoca
 | 
			
		||||
    object_path = service;
 | 
			
		||||
  }
 | 
			
		||||
  if (g_dbus_is_name(bus_name) == FALSE) {
 | 
			
		||||
    g_dbus_method_invocation_return_error(invocation,
 | 
			
		||||
                                          G_DBUS_ERROR,
 | 
			
		||||
                                          G_DBUS_ERROR_INVALID_ARGS,
 | 
			
		||||
                                          "D-Bus bus name '%s' is not valid",
 | 
			
		||||
                                          bus_name);
 | 
			
		||||
    g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
 | 
			
		||||
                                          "D-Bus bus name '%s' is not valid", bus_name);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
  }
 | 
			
		||||
  auto watch = gfWatchFind(obj->hosts_, bus_name, object_path);
 | 
			
		||||
  if (watch != nullptr) {
 | 
			
		||||
    g_dbus_method_invocation_return_error(
 | 
			
		||||
        invocation,
 | 
			
		||||
        G_DBUS_ERROR,
 | 
			
		||||
        G_DBUS_ERROR_INVALID_ARGS,
 | 
			
		||||
        invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
 | 
			
		||||
        "Status Notifier Host with bus name '%s' and object path '%s' is already registered",
 | 
			
		||||
        bus_name,
 | 
			
		||||
        object_path);
 | 
			
		||||
        bus_name, object_path);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
  }
 | 
			
		||||
  watch = gfWatchNew(GF_WATCH_TYPE_HOST, service, bus_name, object_path, obj);
 | 
			
		||||
@@ -93,18 +88,14 @@ gboolean Watcher::handleRegisterItem(Watcher* obj, GDBusMethodInvocation* invoca
 | 
			
		||||
    object_path = service;
 | 
			
		||||
  }
 | 
			
		||||
  if (g_dbus_is_name(bus_name) == FALSE) {
 | 
			
		||||
    g_dbus_method_invocation_return_error(invocation,
 | 
			
		||||
                                          G_DBUS_ERROR,
 | 
			
		||||
                                          G_DBUS_ERROR_INVALID_ARGS,
 | 
			
		||||
                                          "D-Bus bus name '%s' is not valid",
 | 
			
		||||
                                          bus_name);
 | 
			
		||||
    g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
 | 
			
		||||
                                          "D-Bus bus name '%s' is not valid", bus_name);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
  }
 | 
			
		||||
  auto watch = gfWatchFind(obj->items_, bus_name, object_path);
 | 
			
		||||
  if (watch != nullptr) {
 | 
			
		||||
    g_warning("Status Notifier Item with bus name '%s' and object path '%s' is already registered",
 | 
			
		||||
              bus_name,
 | 
			
		||||
              object_path);
 | 
			
		||||
              bus_name, object_path);
 | 
			
		||||
    sn_watcher_complete_register_item(obj->watcher_, invocation);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
  }
 | 
			
		||||
@@ -152,13 +143,8 @@ Watcher::GfWatch* Watcher::gfWatchNew(GfWatchType type, const gchar* service, co
 | 
			
		||||
  watch->service = g_strdup(service);
 | 
			
		||||
  watch->bus_name = g_strdup(bus_name);
 | 
			
		||||
  watch->object_path = g_strdup(object_path);
 | 
			
		||||
  watch->watch_id = g_bus_watch_name(G_BUS_TYPE_SESSION,
 | 
			
		||||
                                     bus_name,
 | 
			
		||||
                                     G_BUS_NAME_WATCHER_FLAGS_NONE,
 | 
			
		||||
                                     nullptr,
 | 
			
		||||
                                     &Watcher::nameVanished,
 | 
			
		||||
                                     watch,
 | 
			
		||||
                                     nullptr);
 | 
			
		||||
  watch->watch_id = g_bus_watch_name(G_BUS_TYPE_SESSION, bus_name, G_BUS_NAME_WATCHER_FLAGS_NONE,
 | 
			
		||||
                                     nullptr, &Watcher::nameVanished, watch, nullptr);
 | 
			
		||||
  return watch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -183,12 +169,12 @@ void Watcher::updateRegisteredItems(SnWatcher* obj) {
 | 
			
		||||
  GVariantBuilder builder;
 | 
			
		||||
  g_variant_builder_init(&builder, G_VARIANT_TYPE("as"));
 | 
			
		||||
  for (GSList* l = items_; l != nullptr; l = g_slist_next(l)) {
 | 
			
		||||
    auto   watch = static_cast<GfWatch*>(l->data);
 | 
			
		||||
    auto watch = static_cast<GfWatch*>(l->data);
 | 
			
		||||
    gchar* item = g_strdup_printf("%s%s", watch->bus_name, watch->object_path);
 | 
			
		||||
    g_variant_builder_add(&builder, "s", item);
 | 
			
		||||
    g_free(item);
 | 
			
		||||
  }
 | 
			
		||||
  GVariant*     variant = g_variant_builder_end(&builder);
 | 
			
		||||
  GVariant* variant = g_variant_builder_end(&builder);
 | 
			
		||||
  const gchar** items = g_variant_get_strv(variant, nullptr);
 | 
			
		||||
  sn_watcher_set_registered_items(obj, items);
 | 
			
		||||
  g_variant_unref(variant);
 | 
			
		||||
 
 | 
			
		||||
@@ -79,11 +79,8 @@ void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BarIpcClient::onConfigUpdate(const swaybar_config& config) {
 | 
			
		||||
  spdlog::info("config update for {}: id {}, mode {}, hidden_state {}",
 | 
			
		||||
               bar_.bar_id,
 | 
			
		||||
               config.id,
 | 
			
		||||
               config.mode,
 | 
			
		||||
               config.hidden_state);
 | 
			
		||||
  spdlog::info("config update for {}: id {}, mode {}, hidden_state {}", bar_.bar_id, config.id,
 | 
			
		||||
               config.mode, config.hidden_state);
 | 
			
		||||
  bar_config_ = config;
 | 
			
		||||
  update();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/sway/ipc/client.hpp"
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules::sway {
 | 
			
		||||
@@ -35,8 +36,8 @@ const std::string Ipc::getSocketPath() const {
 | 
			
		||||
  std::string str;
 | 
			
		||||
  {
 | 
			
		||||
    std::string str_buf;
 | 
			
		||||
    FILE*       in;
 | 
			
		||||
    char        buf[512] = {0};
 | 
			
		||||
    FILE* in;
 | 
			
		||||
    char buf[512] = {0};
 | 
			
		||||
    if ((in = popen("sway --get-socketpath 2>/dev/null", "r")) == nullptr) {
 | 
			
		||||
      throw std::runtime_error("Failed to get socket path");
 | 
			
		||||
    }
 | 
			
		||||
@@ -76,7 +77,7 @@ int Ipc::open(const std::string& socketPath) const {
 | 
			
		||||
struct Ipc::ipc_response Ipc::recv(int fd) {
 | 
			
		||||
  std::string header;
 | 
			
		||||
  header.resize(ipc_header_size_);
 | 
			
		||||
  auto   data32 = reinterpret_cast<uint32_t*>(header.data() + ipc_magic_.size());
 | 
			
		||||
  auto data32 = reinterpret_cast<uint32_t*>(header.data() + ipc_magic_.size());
 | 
			
		||||
  size_t total = 0;
 | 
			
		||||
 | 
			
		||||
  while (total < ipc_header_size_) {
 | 
			
		||||
 
 | 
			
		||||
@@ -51,8 +51,8 @@ void Language::onCmd(const struct Ipc::ipc_response& res) {
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
    auto                        payload = parser_.parse(res.payload);
 | 
			
		||||
    std::vector<std::string>    used_layouts;
 | 
			
		||||
    auto payload = parser_.parse(res.payload);
 | 
			
		||||
    std::vector<std::string> used_layouts;
 | 
			
		||||
    // Display current layout of a device with a maximum count of layouts, expecting that all will
 | 
			
		||||
    // be OK
 | 
			
		||||
    Json::ArrayIndex max_id = 0, max = 0;
 | 
			
		||||
@@ -83,7 +83,7 @@ void Language::onEvent(const struct Ipc::ipc_response& res) {
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
    auto                        payload = parser_.parse(res.payload)["input"];
 | 
			
		||||
    auto payload = parser_.parse(res.payload)["input"];
 | 
			
		||||
    if (payload["type"].asString() == "keyboard") {
 | 
			
		||||
      set_current_layout(payload[XKB_ACTIVE_LAYOUT_NAME_KEY].asString());
 | 
			
		||||
    }
 | 
			
		||||
@@ -95,21 +95,18 @@ void Language::onEvent(const struct Ipc::ipc_response& res) {
 | 
			
		||||
 | 
			
		||||
auto Language::update() -> void {
 | 
			
		||||
  std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
  auto display_layout = trim(fmt::format(format_,
 | 
			
		||||
                                         fmt::arg("short", layout_.short_name),
 | 
			
		||||
                                         fmt::arg("shortDescription", layout_.short_description),
 | 
			
		||||
                                         fmt::arg("long", layout_.full_name),
 | 
			
		||||
                                         fmt::arg("variant", layout_.variant),
 | 
			
		||||
                                         fmt::arg("flag", layout_.country_flag())));
 | 
			
		||||
  auto display_layout = trim(fmt::format(
 | 
			
		||||
      format_, fmt::arg("short", layout_.short_name),
 | 
			
		||||
      fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name),
 | 
			
		||||
      fmt::arg("variant", layout_.variant), fmt::arg("flag", layout_.country_flag())));
 | 
			
		||||
  label_.set_markup(display_layout);
 | 
			
		||||
  if (tooltipEnabled()) {
 | 
			
		||||
    if (tooltip_format_ != "") {
 | 
			
		||||
      auto tooltip_display_layout = trim(fmt::format(tooltip_format_,
 | 
			
		||||
                                                     fmt::arg("short", layout_.short_name),
 | 
			
		||||
                                                     fmt::arg("shortDescription", layout_.short_description),
 | 
			
		||||
                                                     fmt::arg("long", layout_.full_name),
 | 
			
		||||
                                                     fmt::arg("variant", layout_.variant),
 | 
			
		||||
                                                     fmt::arg("flag", layout_.country_flag())));
 | 
			
		||||
      auto tooltip_display_layout = trim(
 | 
			
		||||
          fmt::format(tooltip_format_, fmt::arg("short", layout_.short_name),
 | 
			
		||||
                      fmt::arg("shortDescription", layout_.short_description),
 | 
			
		||||
                      fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant),
 | 
			
		||||
                      fmt::arg("flag", layout_.country_flag())));
 | 
			
		||||
      label_.set_tooltip_markup(tooltip_display_layout);
 | 
			
		||||
    } else {
 | 
			
		||||
      label_.set_tooltip_markup(display_layout);
 | 
			
		||||
@@ -129,7 +126,7 @@ auto Language::set_current_layout(std::string current_layout) -> void {
 | 
			
		||||
auto Language::init_layouts_map(const std::vector<std::string>& used_layouts) -> void {
 | 
			
		||||
  std::map<std::string, std::vector<Layout*>> found_by_short_names;
 | 
			
		||||
  XKBContext xkb_context;
 | 
			
		||||
  auto                                        layout = xkb_context.next_layout();
 | 
			
		||||
  auto layout = xkb_context.next_layout();
 | 
			
		||||
  for (; layout != nullptr; layout = xkb_context.next_layout()) {
 | 
			
		||||
    if (std::find(used_layouts.begin(), used_layouts.end(), layout->full_name) ==
 | 
			
		||||
        used_layouts.end()) {
 | 
			
		||||
@@ -155,8 +152,7 @@ auto Language::init_layouts_map(const std::vector<std::string>& used_layouts) ->
 | 
			
		||||
  std::map<std::string, int> short_name_to_number_map;
 | 
			
		||||
  for (const auto& used_layout_name : used_layouts) {
 | 
			
		||||
    auto found = layouts_map_.find(used_layout_name);
 | 
			
		||||
    if (found == layouts_map_.end())
 | 
			
		||||
      continue;
 | 
			
		||||
    if (found == layouts_map_.end()) continue;
 | 
			
		||||
    auto used_layout = &found->second;
 | 
			
		||||
    auto layouts_with_same_name_list = found_by_short_names[used_layout->short_name];
 | 
			
		||||
    if (layouts_with_same_name_list.size() < 2) {
 | 
			
		||||
@@ -169,10 +165,8 @@ auto Language::init_layouts_map(const std::vector<std::string>& used_layouts) ->
 | 
			
		||||
 | 
			
		||||
    if (displayed_short_flag != static_cast<std::byte>(0)) {
 | 
			
		||||
      int& number = short_name_to_number_map[used_layout->short_name];
 | 
			
		||||
      used_layout->short_name =
 | 
			
		||||
          used_layout->short_name + std::to_string(number);
 | 
			
		||||
      used_layout->short_description =
 | 
			
		||||
          used_layout->short_description + std::to_string(number);
 | 
			
		||||
      used_layout->short_name = used_layout->short_name + std::to_string(number);
 | 
			
		||||
      used_layout->short_description = used_layout->short_description + std::to_string(number);
 | 
			
		||||
      ++number;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -194,18 +188,19 @@ auto Language::XKBContext::next_layout() -> Layout* {
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto        description = std::string(rxkb_layout_get_description(xkb_layout_));
 | 
			
		||||
  auto        name = std::string(rxkb_layout_get_name(xkb_layout_));
 | 
			
		||||
  auto        variant_ = rxkb_layout_get_variant(xkb_layout_);
 | 
			
		||||
  auto description = std::string(rxkb_layout_get_description(xkb_layout_));
 | 
			
		||||
  auto name = std::string(rxkb_layout_get_name(xkb_layout_));
 | 
			
		||||
  auto variant_ = rxkb_layout_get_variant(xkb_layout_);
 | 
			
		||||
  std::string variant = variant_ == nullptr ? "" : std::string(variant_);
 | 
			
		||||
  auto        short_description_ = rxkb_layout_get_brief(xkb_layout_);
 | 
			
		||||
  auto short_description_ = rxkb_layout_get_brief(xkb_layout_);
 | 
			
		||||
  std::string short_description;
 | 
			
		||||
  if (short_description_ != nullptr) {
 | 
			
		||||
    short_description = std::string(short_description_);
 | 
			
		||||
    base_layouts_by_name_.emplace(name, xkb_layout_);
 | 
			
		||||
  } else {
 | 
			
		||||
    auto base_layout = base_layouts_by_name_[name];
 | 
			
		||||
    short_description = base_layout == nullptr ? "" : std::string(rxkb_layout_get_brief(base_layout));
 | 
			
		||||
    short_description =
 | 
			
		||||
        base_layout == nullptr ? "" : std::string(rxkb_layout_get_brief(base_layout));
 | 
			
		||||
  }
 | 
			
		||||
  delete layout_;
 | 
			
		||||
  layout_ = new Layout{description, name, variant, short_description};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/sway/mode.hpp"
 | 
			
		||||
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules::sway {
 | 
			
		||||
@@ -21,7 +22,7 @@ Mode::Mode(const std::string& id, const Json::Value& config)
 | 
			
		||||
void Mode::onEvent(const struct Ipc::ipc_response& res) {
 | 
			
		||||
  try {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
    auto                        payload = parser_.parse(res.payload);
 | 
			
		||||
    auto payload = parser_.parse(res.payload);
 | 
			
		||||
    if (payload["change"] != "default") {
 | 
			
		||||
      if (payload["pango_markup"].asBool()) {
 | 
			
		||||
        mode_ = payload["change"].asString();
 | 
			
		||||
 
 | 
			
		||||
@@ -70,11 +70,11 @@ std::optional<Glib::ustring> getIconName(const std::string& app_id) {
 | 
			
		||||
    }
 | 
			
		||||
    return icon_name;
 | 
			
		||||
  } catch (Glib::FileError& error) {
 | 
			
		||||
    spdlog::warn(
 | 
			
		||||
        "Error while loading desktop file {}: {}", desktop_file_path.value(), error.what().c_str());
 | 
			
		||||
    spdlog::warn("Error while loading desktop file {}: {}", desktop_file_path.value(),
 | 
			
		||||
                 error.what().c_str());
 | 
			
		||||
  } catch (Glib::KeyFileError& error) {
 | 
			
		||||
    spdlog::warn(
 | 
			
		||||
        "Error while loading desktop file {}: {}", desktop_file_path.value(), error.what().c_str());
 | 
			
		||||
    spdlog::warn("Error while loading desktop file {}: {}", desktop_file_path.value(),
 | 
			
		||||
                 error.what().c_str());
 | 
			
		||||
  }
 | 
			
		||||
  return {};
 | 
			
		||||
}
 | 
			
		||||
@@ -114,8 +114,8 @@ auto Window::update() -> void {
 | 
			
		||||
    bar_.window.get_style_context()->remove_class("solo");
 | 
			
		||||
    bar_.window.get_style_context()->remove_class("empty");
 | 
			
		||||
  }
 | 
			
		||||
  label_.set_markup(fmt::format(format_, fmt::arg("title", rewriteTitle(window_)),
 | 
			
		||||
                                fmt::arg("app_id", app_id_)));
 | 
			
		||||
  label_.set_markup(
 | 
			
		||||
      fmt::format(format_, fmt::arg("title", rewriteTitle(window_)), fmt::arg("app_id", app_id_)));
 | 
			
		||||
  if (tooltipEnabled()) {
 | 
			
		||||
    label_.set_tooltip_text(window_);
 | 
			
		||||
  }
 | 
			
		||||
@@ -126,28 +126,26 @@ auto Window::update() -> void {
 | 
			
		||||
int leafNodesInWorkspace(const Json::Value& node) {
 | 
			
		||||
  auto const& nodes = node["nodes"];
 | 
			
		||||
  auto const& floating_nodes = node["floating_nodes"];
 | 
			
		||||
  if(nodes.empty() && floating_nodes.empty()) {
 | 
			
		||||
    if(node["type"] == "workspace")
 | 
			
		||||
  if (nodes.empty() && floating_nodes.empty()) {
 | 
			
		||||
    if (node["type"] == "workspace")
 | 
			
		||||
      return 0;
 | 
			
		||||
    else
 | 
			
		||||
      return 1;
 | 
			
		||||
  }
 | 
			
		||||
  int sum = 0;
 | 
			
		||||
  if (!nodes.empty()) {
 | 
			
		||||
    for(auto const& node : nodes)
 | 
			
		||||
      sum += leafNodesInWorkspace(node);
 | 
			
		||||
    for (auto const& node : nodes) sum += leafNodesInWorkspace(node);
 | 
			
		||||
  }
 | 
			
		||||
  if (!floating_nodes.empty()) {
 | 
			
		||||
    for(auto const& node : floating_nodes)
 | 
			
		||||
      sum += leafNodesInWorkspace(node);
 | 
			
		||||
    for (auto const& node : floating_nodes) sum += leafNodesInWorkspace(node);
 | 
			
		||||
  }
 | 
			
		||||
  return sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::tuple<std::size_t, int, std::string, std::string> gfnWithWorkspace(
 | 
			
		||||
    const Json::Value& nodes, std::string& output, const Json::Value& config_,
 | 
			
		||||
    const Bar& bar_, Json::Value& parentWorkspace) {
 | 
			
		||||
  for(auto const& node : nodes) {
 | 
			
		||||
    const Json::Value& nodes, std::string& output, const Json::Value& config_, const Bar& bar_,
 | 
			
		||||
    Json::Value& parentWorkspace) {
 | 
			
		||||
  for (auto const& node : nodes) {
 | 
			
		||||
    if (node["output"].isString()) {
 | 
			
		||||
      output = node["output"].asString();
 | 
			
		||||
    }
 | 
			
		||||
@@ -156,25 +154,22 @@ std::tuple<std::size_t, int, std::string, std::string> gfnWithWorkspace(
 | 
			
		||||
      if ((!config_["all-outputs"].asBool() && output == bar_.output->name) ||
 | 
			
		||||
          config_["all-outputs"].asBool()) {
 | 
			
		||||
        auto app_id = node["app_id"].isString() ? node["app_id"].asString()
 | 
			
		||||
                      : node["window_properties"]["instance"].asString();
 | 
			
		||||
                                                : node["window_properties"]["instance"].asString();
 | 
			
		||||
        int nb = node.size();
 | 
			
		||||
        if(parentWorkspace != 0)
 | 
			
		||||
          nb = leafNodesInWorkspace(parentWorkspace);
 | 
			
		||||
        return {nb,
 | 
			
		||||
          node["id"].asInt(),
 | 
			
		||||
          Glib::Markup::escape_text(node["name"].asString()),
 | 
			
		||||
          app_id};
 | 
			
		||||
        if (parentWorkspace != 0) nb = leafNodesInWorkspace(parentWorkspace);
 | 
			
		||||
        return {nb, node["id"].asInt(), Glib::Markup::escape_text(node["name"].asString()), app_id};
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // iterate
 | 
			
		||||
    if(node["type"] == "workspace")
 | 
			
		||||
      parentWorkspace = node;
 | 
			
		||||
    auto [nb, id, name, app_id] = gfnWithWorkspace(node["nodes"], output, config_, bar_, parentWorkspace);
 | 
			
		||||
    if (node["type"] == "workspace") parentWorkspace = node;
 | 
			
		||||
    auto [nb, id, name, app_id] =
 | 
			
		||||
        gfnWithWorkspace(node["nodes"], output, config_, bar_, parentWorkspace);
 | 
			
		||||
    if (id > -1 && !name.empty()) {
 | 
			
		||||
      return {nb, id, name, app_id};
 | 
			
		||||
    }
 | 
			
		||||
    // Search for floating node
 | 
			
		||||
    std::tie(nb, id, name, app_id) = gfnWithWorkspace(node["floating_nodes"], output, config_, bar_, parentWorkspace);
 | 
			
		||||
    std::tie(nb, id, name, app_id) =
 | 
			
		||||
        gfnWithWorkspace(node["floating_nodes"], output, config_, bar_, parentWorkspace);
 | 
			
		||||
    if (id > -1 && !name.empty()) {
 | 
			
		||||
      return {nb, id, name, app_id};
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ namespace waybar::modules::sway {
 | 
			
		||||
int Workspaces::convertWorkspaceNameToNum(std::string name) {
 | 
			
		||||
  if (isdigit(name[0])) {
 | 
			
		||||
    errno = 0;
 | 
			
		||||
    char *    endptr = NULL;
 | 
			
		||||
    char *endptr = NULL;
 | 
			
		||||
    long long parsed_num = strtoll(name.c_str(), &endptr, 10);
 | 
			
		||||
    if (errno != 0 || parsed_num > INT32_MAX || parsed_num < 0 || endptr == name.c_str()) {
 | 
			
		||||
      return -1;
 | 
			
		||||
@@ -65,11 +65,9 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
 | 
			
		||||
    try {
 | 
			
		||||
      {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
        auto                        payload = parser_.parse(res.payload);
 | 
			
		||||
        auto payload = parser_.parse(res.payload);
 | 
			
		||||
        workspaces_.clear();
 | 
			
		||||
        std::copy_if(payload.begin(),
 | 
			
		||||
                     payload.end(),
 | 
			
		||||
                     std::back_inserter(workspaces_),
 | 
			
		||||
        std::copy_if(payload.begin(), payload.end(), std::back_inserter(workspaces_),
 | 
			
		||||
                     [&](const auto &workspace) {
 | 
			
		||||
                       return !config_["all-outputs"].asBool()
 | 
			
		||||
                                  ? workspace["output"].asString() == bar_.output->name
 | 
			
		||||
@@ -78,12 +76,12 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
 | 
			
		||||
 | 
			
		||||
        // adding persistent workspaces (as per the config file)
 | 
			
		||||
        if (config_["persistent_workspaces"].isObject()) {
 | 
			
		||||
          const Json::Value &            p_workspaces = config_["persistent_workspaces"];
 | 
			
		||||
          const Json::Value &p_workspaces = config_["persistent_workspaces"];
 | 
			
		||||
          const std::vector<std::string> p_workspaces_names = p_workspaces.getMemberNames();
 | 
			
		||||
 | 
			
		||||
          for (const std::string &p_w_name : p_workspaces_names) {
 | 
			
		||||
            const Json::Value &p_w = p_workspaces[p_w_name];
 | 
			
		||||
            auto               it =
 | 
			
		||||
            auto it =
 | 
			
		||||
                std::find_if(payload.begin(), payload.end(), [&p_w_name](const Json::Value &node) {
 | 
			
		||||
                  return node["name"].asString() == p_w_name;
 | 
			
		||||
                });
 | 
			
		||||
@@ -133,10 +131,10 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
 | 
			
		||||
        // unnumbered workspaces behind numbered ones when computing the sort
 | 
			
		||||
        // attribute.
 | 
			
		||||
        int max_num = -1;
 | 
			
		||||
        for (auto & workspace : workspaces_) {
 | 
			
		||||
        for (auto &workspace : workspaces_) {
 | 
			
		||||
          max_num = std::max(workspace["num"].asInt(), max_num);
 | 
			
		||||
        }
 | 
			
		||||
        for (auto & workspace : workspaces_) {
 | 
			
		||||
        for (auto &workspace : workspaces_) {
 | 
			
		||||
          auto workspace_num = workspace["num"].asInt();
 | 
			
		||||
          if (workspace_num > -1) {
 | 
			
		||||
            workspace["sort"] = workspace_num;
 | 
			
		||||
@@ -144,13 +142,12 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
 | 
			
		||||
            workspace["sort"] = ++max_num;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        std::sort(workspaces_.begin(),
 | 
			
		||||
                  workspaces_.end(),
 | 
			
		||||
        std::sort(workspaces_.begin(), workspaces_.end(),
 | 
			
		||||
                  [](const Json::Value &lhs, const Json::Value &rhs) {
 | 
			
		||||
                    auto lname = lhs["name"].asString();
 | 
			
		||||
                    auto rname = rhs["name"].asString();
 | 
			
		||||
                    int  l = lhs["sort"].asInt();
 | 
			
		||||
                    int  r = rhs["sort"].asInt();
 | 
			
		||||
                    int l = lhs["sort"].asInt();
 | 
			
		||||
                    int r = rhs["sort"].asInt();
 | 
			
		||||
 | 
			
		||||
                    if (l == r) {
 | 
			
		||||
                      // In case both integers are the same, lexicographical
 | 
			
		||||
@@ -161,7 +158,6 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
 | 
			
		||||
 | 
			
		||||
                    return l < r;
 | 
			
		||||
                  });
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
      dp.emit();
 | 
			
		||||
    } catch (const std::exception &e) {
 | 
			
		||||
@@ -173,9 +169,8 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
 | 
			
		||||
bool Workspaces::filterButtons() {
 | 
			
		||||
  bool needReorder = false;
 | 
			
		||||
  for (auto it = buttons_.begin(); it != buttons_.end();) {
 | 
			
		||||
    auto ws = std::find_if(workspaces_.begin(), workspaces_.end(), [it](const auto &node) {
 | 
			
		||||
      return node["name"].asString() == it->first;
 | 
			
		||||
    });
 | 
			
		||||
    auto ws = std::find_if(workspaces_.begin(), workspaces_.end(),
 | 
			
		||||
                           [it](const auto &node) { return node["name"].asString() == it->first; });
 | 
			
		||||
    if (ws == workspaces_.end() ||
 | 
			
		||||
        (!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) {
 | 
			
		||||
      it = buttons_.erase(it);
 | 
			
		||||
@@ -189,7 +184,7 @@ bool Workspaces::filterButtons() {
 | 
			
		||||
 | 
			
		||||
auto Workspaces::update() -> void {
 | 
			
		||||
  std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
  bool                        needReorder = filterButtons();
 | 
			
		||||
  bool needReorder = filterButtons();
 | 
			
		||||
  for (auto it = workspaces_.begin(); it != workspaces_.end(); ++it) {
 | 
			
		||||
    auto bit = buttons_.find((*it)["name"].asString());
 | 
			
		||||
    if (bit == buttons_.end()) {
 | 
			
		||||
@@ -231,10 +226,8 @@ auto Workspaces::update() -> void {
 | 
			
		||||
    std::string output = (*it)["name"].asString();
 | 
			
		||||
    if (config_["format"].isString()) {
 | 
			
		||||
      auto format = config_["format"].asString();
 | 
			
		||||
      output = fmt::format(format,
 | 
			
		||||
                           fmt::arg("icon", getIcon(output, *it)),
 | 
			
		||||
                           fmt::arg("value", output),
 | 
			
		||||
                           fmt::arg("name", trimWorkspaceName(output)),
 | 
			
		||||
      output = fmt::format(format, fmt::arg("icon", getIcon(output, *it)),
 | 
			
		||||
                           fmt::arg("value", output), fmt::arg("name", trimWorkspaceName(output)),
 | 
			
		||||
                           fmt::arg("index", (*it)["num"].asString()));
 | 
			
		||||
    }
 | 
			
		||||
    if (!config_["disable-markup"].asBool()) {
 | 
			
		||||
@@ -249,7 +242,7 @@ auto Workspaces::update() -> void {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Gtk::Button &Workspaces::addButton(const Json::Value &node) {
 | 
			
		||||
  auto   pair = buttons_.emplace(node["name"].asString(), node["name"].asString());
 | 
			
		||||
  auto pair = buttons_.emplace(node["name"].asString(), node["name"].asString());
 | 
			
		||||
  auto &&button = pair.first->second;
 | 
			
		||||
  box_.pack_start(button, false, false, 0);
 | 
			
		||||
  button.set_name("sway-workspace-" + node["name"].asString());
 | 
			
		||||
@@ -258,22 +251,18 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) {
 | 
			
		||||
    button.signal_pressed().connect([this, node] {
 | 
			
		||||
      try {
 | 
			
		||||
        if (node["target_output"].isString()) {
 | 
			
		||||
          ipc_.sendCmd(
 | 
			
		||||
              IPC_COMMAND,
 | 
			
		||||
              fmt::format(workspace_switch_cmd_ + "; move workspace to output \"{}\"; " + workspace_switch_cmd_,
 | 
			
		||||
                          "--no-auto-back-and-forth",
 | 
			
		||||
                          node["name"].asString(),
 | 
			
		||||
                          node["target_output"].asString(),
 | 
			
		||||
                          "--no-auto-back-and-forth",
 | 
			
		||||
                          node["name"].asString()));
 | 
			
		||||
          ipc_.sendCmd(IPC_COMMAND,
 | 
			
		||||
                       fmt::format(workspace_switch_cmd_ + "; move workspace to output \"{}\"; " +
 | 
			
		||||
                                       workspace_switch_cmd_,
 | 
			
		||||
                                   "--no-auto-back-and-forth", node["name"].asString(),
 | 
			
		||||
                                   node["target_output"].asString(), "--no-auto-back-and-forth",
 | 
			
		||||
                                   node["name"].asString()));
 | 
			
		||||
        } else {
 | 
			
		||||
          ipc_.sendCmd(
 | 
			
		||||
              IPC_COMMAND,
 | 
			
		||||
              fmt::format("workspace {} \"{}\"",
 | 
			
		||||
                          config_["disable-auto-back-and-forth"].asBool()
 | 
			
		||||
                            ? "--no-auto-back-and-forth"
 | 
			
		||||
                            : "",
 | 
			
		||||
                          node["name"].asString()));
 | 
			
		||||
          ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace {} \"{}\"",
 | 
			
		||||
                                                config_["disable-auto-back-and-forth"].asBool()
 | 
			
		||||
                                                    ? "--no-auto-back-and-forth"
 | 
			
		||||
                                                    : "",
 | 
			
		||||
                                                node["name"].asString()));
 | 
			
		||||
        }
 | 
			
		||||
      } catch (const std::exception &e) {
 | 
			
		||||
        spdlog::error("Workspaces: {}", e.what());
 | 
			
		||||
@@ -316,9 +305,8 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
  std::string name;
 | 
			
		||||
  {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(mutex_);
 | 
			
		||||
    auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
 | 
			
		||||
      return workspace["focused"].asBool();
 | 
			
		||||
    });
 | 
			
		||||
    auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
 | 
			
		||||
                           [](const auto &workspace) { return workspace["focused"].asBool(); });
 | 
			
		||||
    if (it == workspaces_.end()) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
@@ -334,9 +322,7 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  try {
 | 
			
		||||
    ipc_.sendCmd(
 | 
			
		||||
        IPC_COMMAND,
 | 
			
		||||
        fmt::format(workspace_switch_cmd_, "--no-auto-back-and-forth", name));
 | 
			
		||||
    ipc_.sendCmd(IPC_COMMAND, fmt::format(workspace_switch_cmd_, "--no-auto-back-and-forth", name));
 | 
			
		||||
  } catch (const std::exception &e) {
 | 
			
		||||
    spdlog::error("Workspaces: {}", e.what());
 | 
			
		||||
  }
 | 
			
		||||
@@ -344,7 +330,7 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::string Workspaces::getCycleWorkspace(std::vector<Json::Value>::iterator it,
 | 
			
		||||
                                                bool                               prev) const {
 | 
			
		||||
                                                bool prev) const {
 | 
			
		||||
  if (prev && it == workspaces_.begin() && !config_["disable-scroll-wraparound"].asBool()) {
 | 
			
		||||
    return (*(--workspaces_.end()))["name"].asString();
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "modules/temperature.hpp"
 | 
			
		||||
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
 | 
			
		||||
waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config)
 | 
			
		||||
@@ -6,7 +7,10 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
 | 
			
		||||
  if (config_["hwmon-path"].isString()) {
 | 
			
		||||
    file_path_ = config_["hwmon-path"].asString();
 | 
			
		||||
  } else if (config_["hwmon-path-abs"].isString() && config_["input-filename"].isString()) {
 | 
			
		||||
    file_path_ = (*std::filesystem::directory_iterator(config_["hwmon-path-abs"].asString())).path().string() + "/" + config_["input-filename"].asString();
 | 
			
		||||
    file_path_ = (*std::filesystem::directory_iterator(config_["hwmon-path-abs"].asString()))
 | 
			
		||||
                     .path()
 | 
			
		||||
                     .string() +
 | 
			
		||||
                 "/" + config_["input-filename"].asString();
 | 
			
		||||
  } else {
 | 
			
		||||
    auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
 | 
			
		||||
    file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
 | 
			
		||||
@@ -35,7 +39,7 @@ auto waybar::modules::Temperature::update() -> void {
 | 
			
		||||
    label_.get_style_context()->remove_class("critical");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if(format.empty()) {
 | 
			
		||||
  if (format.empty()) {
 | 
			
		||||
    event_box_.hide();
 | 
			
		||||
    return;
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -43,8 +47,7 @@ auto waybar::modules::Temperature::update() -> void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto max_temp = config_["critical-threshold"].isInt() ? config_["critical-threshold"].asInt() : 0;
 | 
			
		||||
  label_.set_markup(fmt::format(format,
 | 
			
		||||
                                fmt::arg("temperatureC", temperature_c),
 | 
			
		||||
  label_.set_markup(fmt::format(format, fmt::arg("temperatureC", temperature_c),
 | 
			
		||||
                                fmt::arg("temperatureF", temperature_f),
 | 
			
		||||
                                fmt::arg("temperatureK", temperature_k),
 | 
			
		||||
                                fmt::arg("icon", getIcon(temperature_c, "", max_temp))));
 | 
			
		||||
@@ -53,10 +56,9 @@ auto waybar::modules::Temperature::update() -> void {
 | 
			
		||||
    if (config_["tooltip-format"].isString()) {
 | 
			
		||||
      tooltip_format = config_["tooltip-format"].asString();
 | 
			
		||||
    }
 | 
			
		||||
    label_.set_tooltip_text(fmt::format(tooltip_format,
 | 
			
		||||
                                fmt::arg("temperatureC", temperature_c),
 | 
			
		||||
                                fmt::arg("temperatureF", temperature_f),
 | 
			
		||||
                                fmt::arg("temperatureK", temperature_k)));
 | 
			
		||||
    label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c),
 | 
			
		||||
                                        fmt::arg("temperatureF", temperature_f),
 | 
			
		||||
                                        fmt::arg("temperatureK", temperature_k)));
 | 
			
		||||
  }
 | 
			
		||||
  // Call parent update
 | 
			
		||||
  ALabel::update();
 | 
			
		||||
@@ -72,7 +74,7 @@ float waybar::modules::Temperature::getTemperature() {
 | 
			
		||||
    getline(temp, line);
 | 
			
		||||
  }
 | 
			
		||||
  temp.close();
 | 
			
		||||
  auto                           temperature_c = std::strtol(line.c_str(), nullptr, 10) / 1000.0;
 | 
			
		||||
  auto temperature_c = std::strtol(line.c_str(), nullptr, 10) / 1000.0;
 | 
			
		||||
  return temperature_c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -68,13 +68,9 @@ UPower::UPower(const std::string& id, const Json::Value& config)
 | 
			
		||||
    box_.signal_query_tooltip().connect(sigc::mem_fun(*this, &UPower::show_tooltip_callback));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  upowerWatcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
 | 
			
		||||
                                      "org.freedesktop.UPower",
 | 
			
		||||
                                      G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
 | 
			
		||||
                                      upowerAppear,
 | 
			
		||||
                                      upowerDisappear,
 | 
			
		||||
                                      this,
 | 
			
		||||
                                      NULL);
 | 
			
		||||
  upowerWatcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM, "org.freedesktop.UPower",
 | 
			
		||||
                                      G_BUS_NAME_WATCHER_FLAGS_AUTO_START, upowerAppear,
 | 
			
		||||
                                      upowerDisappear, this, NULL);
 | 
			
		||||
 | 
			
		||||
  GError* error = NULL;
 | 
			
		||||
  client = up_client_new_full(NULL, &error);
 | 
			
		||||
@@ -87,16 +83,10 @@ UPower::UPower(const std::string& id, const Json::Value& config)
 | 
			
		||||
  if (!login1_connection) {
 | 
			
		||||
    throw std::runtime_error("Unable to connect to the SYSTEM Bus!...");
 | 
			
		||||
  } else {
 | 
			
		||||
    login1_id = g_dbus_connection_signal_subscribe(login1_connection,
 | 
			
		||||
                                                   "org.freedesktop.login1",
 | 
			
		||||
                                                   "org.freedesktop.login1.Manager",
 | 
			
		||||
                                                   "PrepareForSleep",
 | 
			
		||||
                                                   "/org/freedesktop/login1",
 | 
			
		||||
                                                   NULL,
 | 
			
		||||
                                                   G_DBUS_SIGNAL_FLAGS_NONE,
 | 
			
		||||
                                                   prepareForSleep_cb,
 | 
			
		||||
                                                   this,
 | 
			
		||||
                                                   NULL);
 | 
			
		||||
    login1_id = g_dbus_connection_signal_subscribe(
 | 
			
		||||
        login1_connection, "org.freedesktop.login1", "org.freedesktop.login1.Manager",
 | 
			
		||||
        "PrepareForSleep", "/org/freedesktop/login1", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
 | 
			
		||||
        prepareForSleep_cb, this, NULL);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  event_box_.signal_button_press_event().connect(sigc::mem_fun(*this, &UPower::handleToggle));
 | 
			
		||||
@@ -284,26 +274,15 @@ auto UPower::update() -> void {
 | 
			
		||||
  // Don't update widget if the UPower service isn't running
 | 
			
		||||
  if (!upowerRunning) return;
 | 
			
		||||
 | 
			
		||||
  UpDeviceKind  kind;
 | 
			
		||||
  UpDeviceKind kind;
 | 
			
		||||
  UpDeviceState state;
 | 
			
		||||
  double        percentage;
 | 
			
		||||
  gint64        time_empty;
 | 
			
		||||
  gint64        time_full;
 | 
			
		||||
  gchar*        icon_name;
 | 
			
		||||
  double percentage;
 | 
			
		||||
  gint64 time_empty;
 | 
			
		||||
  gint64 time_full;
 | 
			
		||||
  gchar* icon_name;
 | 
			
		||||
 | 
			
		||||
  g_object_get(displayDevice,
 | 
			
		||||
               "kind",
 | 
			
		||||
               &kind,
 | 
			
		||||
               "state",
 | 
			
		||||
               &state,
 | 
			
		||||
               "percentage",
 | 
			
		||||
               &percentage,
 | 
			
		||||
               "icon-name",
 | 
			
		||||
               &icon_name,
 | 
			
		||||
               "time-to-empty",
 | 
			
		||||
               &time_empty,
 | 
			
		||||
               "time-to-full",
 | 
			
		||||
               &time_full,
 | 
			
		||||
  g_object_get(displayDevice, "kind", &kind, "state", &state, "percentage", &percentage,
 | 
			
		||||
               "icon-name", &icon_name, "time-to-empty", &time_empty, "time-to-full", &time_full,
 | 
			
		||||
               NULL);
 | 
			
		||||
 | 
			
		||||
  bool displayDeviceValid =
 | 
			
		||||
@@ -357,9 +336,9 @@ auto UPower::update() -> void {
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  std::string label_format = fmt::format(showAltText ? format_alt : format,
 | 
			
		||||
                                         fmt::arg("percentage", percentString),
 | 
			
		||||
                                         fmt::arg("time", time_format));
 | 
			
		||||
  std::string label_format =
 | 
			
		||||
      fmt::format(showAltText ? format_alt : format, fmt::arg("percentage", percentString),
 | 
			
		||||
                  fmt::arg("time", time_format));
 | 
			
		||||
  // Only set the label text if it doesn't only contain spaces
 | 
			
		||||
  bool onlySpaces = true;
 | 
			
		||||
  for (auto& character : label_format) {
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ uint UPowerTooltip::updateTooltip(Devices& devices) {
 | 
			
		||||
  uint deviceCount = 0;
 | 
			
		||||
  // Adds all valid devices
 | 
			
		||||
  for (auto pair : devices) {
 | 
			
		||||
    UpDevice*   device = pair.second;
 | 
			
		||||
    UpDevice* device = pair.second;
 | 
			
		||||
    std::string objectPath = pair.first;
 | 
			
		||||
 | 
			
		||||
    if (!G_IS_OBJECT(device)) continue;
 | 
			
		||||
@@ -43,23 +43,13 @@ uint UPowerTooltip::updateTooltip(Devices& devices) {
 | 
			
		||||
    Gtk::Box* box = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, tooltipSpacing);
 | 
			
		||||
 | 
			
		||||
    UpDeviceKind kind;
 | 
			
		||||
    double       percentage;
 | 
			
		||||
    gchar*       native_path;
 | 
			
		||||
    gchar*       model;
 | 
			
		||||
    gchar*       icon_name;
 | 
			
		||||
    double percentage;
 | 
			
		||||
    gchar* native_path;
 | 
			
		||||
    gchar* model;
 | 
			
		||||
    gchar* icon_name;
 | 
			
		||||
 | 
			
		||||
    g_object_get(device,
 | 
			
		||||
                 "kind",
 | 
			
		||||
                 &kind,
 | 
			
		||||
                 "percentage",
 | 
			
		||||
                 &percentage,
 | 
			
		||||
                 "native-path",
 | 
			
		||||
                 &native_path,
 | 
			
		||||
                 "model",
 | 
			
		||||
                 &model,
 | 
			
		||||
                 "icon-name",
 | 
			
		||||
                 &icon_name,
 | 
			
		||||
                 NULL);
 | 
			
		||||
    g_object_get(device, "kind", &kind, "percentage", &percentage, "native-path", &native_path,
 | 
			
		||||
                 "model", &model, "icon-name", &icon_name, NULL);
 | 
			
		||||
 | 
			
		||||
    // Skip Line_Power and BAT0 devices
 | 
			
		||||
    if (kind == UP_DEVICE_KIND_LINE_POWER || native_path == NULL || strlen(native_path) == 0 ||
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -13,8 +13,8 @@
 | 
			
		||||
 | 
			
		||||
namespace waybar::modules::wlr {
 | 
			
		||||
 | 
			
		||||
uint32_t                           WorkspaceGroup::workspace_global_id = 0;
 | 
			
		||||
uint32_t                           WorkspaceManager::group_global_id = 0;
 | 
			
		||||
uint32_t WorkspaceGroup::workspace_global_id = 0;
 | 
			
		||||
uint32_t WorkspaceManager::group_global_id = 0;
 | 
			
		||||
std::map<std::string, std::string> Workspace::icons_map_;
 | 
			
		||||
 | 
			
		||||
WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar,
 | 
			
		||||
@@ -156,8 +156,7 @@ WorkspaceManager::~WorkspaceManager() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto WorkspaceManager::remove_workspace_group(uint32_t id) -> void {
 | 
			
		||||
  auto it = std::find_if(groups_.begin(),
 | 
			
		||||
                         groups_.end(),
 | 
			
		||||
  auto it = std::find_if(groups_.begin(), groups_.end(),
 | 
			
		||||
                         [id](const std::unique_ptr<WorkspaceGroup> &g) { return g->id() == id; });
 | 
			
		||||
 | 
			
		||||
  if (it == groups_.end()) {
 | 
			
		||||
@@ -170,7 +169,7 @@ auto WorkspaceManager::remove_workspace_group(uint32_t id) -> void {
 | 
			
		||||
auto WorkspaceManager::commit() -> void { zext_workspace_manager_v1_commit(workspace_manager_); }
 | 
			
		||||
 | 
			
		||||
WorkspaceGroup::WorkspaceGroup(const Bar &bar, Gtk::Box &box, const Json::Value &config,
 | 
			
		||||
                               WorkspaceManager               &manager,
 | 
			
		||||
                               WorkspaceManager &manager,
 | 
			
		||||
                               zext_workspace_group_handle_v1 *workspace_group_handle, uint32_t id)
 | 
			
		||||
    : bar_(bar),
 | 
			
		||||
      box_(box),
 | 
			
		||||
@@ -257,8 +256,7 @@ auto WorkspaceGroup::update() -> void {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto WorkspaceGroup::remove_workspace(uint32_t id) -> void {
 | 
			
		||||
  auto it = std::find_if(workspaces_.begin(),
 | 
			
		||||
                         workspaces_.end(),
 | 
			
		||||
  auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
 | 
			
		||||
                         [id](const std::unique_ptr<Workspace> &w) { return w->id() == id; });
 | 
			
		||||
 | 
			
		||||
  if (it == workspaces_.end()) {
 | 
			
		||||
@@ -353,8 +351,8 @@ Workspace::~Workspace() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Workspace::update() -> void {
 | 
			
		||||
  label_.set_markup(fmt::format(
 | 
			
		||||
      format_, fmt::arg("name", name_), fmt::arg("icon", with_icon_ ? get_icon() : "")));
 | 
			
		||||
  label_.set_markup(fmt::format(format_, fmt::arg("name", name_),
 | 
			
		||||
                                fmt::arg("icon", with_icon_ ? get_icon() : "")));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Workspace::handle_state(const std::vector<uint32_t> &state) -> void {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#include "modules/wlr/workspace_manager_binding.hpp"
 | 
			
		||||
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
 | 
			
		||||
#include "client.hpp"
 | 
			
		||||
@@ -23,7 +24,7 @@ static const wl_registry_listener registry_listener_impl = {.global = handle_glo
 | 
			
		||||
                                                            .global_remove = handle_global_remove};
 | 
			
		||||
 | 
			
		||||
void add_registry_listener(void *data) {
 | 
			
		||||
  wl_display * display = Client::inst()->wl_display;
 | 
			
		||||
  wl_display *display = Client::inst()->wl_display;
 | 
			
		||||
  wl_registry *registry = wl_display_get_registry(display);
 | 
			
		||||
 | 
			
		||||
  wl_registry_add_listener(registry, ®istry_listener_impl, data);
 | 
			
		||||
@@ -89,7 +90,7 @@ static const zext_workspace_group_handle_v1_listener workspace_group_impl = {
 | 
			
		||||
    .remove = workspace_group_handle_remove};
 | 
			
		||||
 | 
			
		||||
void add_workspace_group_listener(zext_workspace_group_handle_v1 *workspace_group_handle,
 | 
			
		||||
                                  void *                          data) {
 | 
			
		||||
                                  void *data) {
 | 
			
		||||
  zext_workspace_group_handle_v1_add_listener(workspace_group_handle, &workspace_group_impl, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -100,7 +101,7 @@ void workspace_handle_name(void *data, struct zext_workspace_handle_v1 *_, const
 | 
			
		||||
void workspace_handle_coordinates(void *data, struct zext_workspace_handle_v1 *_,
 | 
			
		||||
                                  struct wl_array *coordinates) {
 | 
			
		||||
  std::vector<uint32_t> coords_vec;
 | 
			
		||||
  auto                  coords = static_cast<uint32_t *>(coordinates->data);
 | 
			
		||||
  auto coords = static_cast<uint32_t *>(coordinates->data);
 | 
			
		||||
  for (size_t i = 0; i < coordinates->size / sizeof(uint32_t); ++i) {
 | 
			
		||||
    coords_vec.push_back(coords[i]);
 | 
			
		||||
  }
 | 
			
		||||
@@ -111,7 +112,7 @@ void workspace_handle_coordinates(void *data, struct zext_workspace_handle_v1 *_
 | 
			
		||||
void workspace_handle_state(void *data, struct zext_workspace_handle_v1 *workspace_handle,
 | 
			
		||||
                            struct wl_array *state) {
 | 
			
		||||
  std::vector<uint32_t> state_vec;
 | 
			
		||||
  auto                  states = static_cast<uint32_t *>(state->data);
 | 
			
		||||
  auto states = static_cast<uint32_t *>(state->data);
 | 
			
		||||
  for (size_t i = 0; i < state->size / sizeof(uint32_t); ++i) {
 | 
			
		||||
    state_vec.push_back(states[i]);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user