Merge remote-tracking branch 'origin/master' into refactor/generic-tooltip
# Conflicts: # src/modules/disk.cpp
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ALabel.hpp"
|
#include "ALabel.hpp"
|
||||||
#include "util/format.hpp"
|
#include "util/format.hpp"
|
||||||
@@ -19,7 +20,9 @@ class Disk : public ALabel {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
util::SleeperThread thread_;
|
util::SleeperThread thread_;
|
||||||
std::string path_;
|
std::string header_;
|
||||||
|
std::vector<std::string> paths_;
|
||||||
|
std::string separator_;
|
||||||
std::string unit_;
|
std::string unit_;
|
||||||
|
|
||||||
float calc_specific_divisor(const std::string& divisor);
|
float calc_specific_divisor(const std::string& divisor);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class Tags : public waybar::AModule {
|
|||||||
const waybar::Bar& bar_;
|
const waybar::Bar& bar_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
std::vector<Gtk::Button> buttons_;
|
std::vector<Gtk::Button> buttons_;
|
||||||
|
bool hide_vacant_;
|
||||||
struct zdwl_ipc_output_v2* output_status_;
|
struct zdwl_ipc_output_v2* output_status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Mpris : public ALabel {
|
|||||||
|
|
||||||
std::optional<std::string> artist;
|
std::optional<std::string> artist;
|
||||||
std::optional<std::string> album;
|
std::optional<std::string> album;
|
||||||
|
std::optional<std::string> album_artist;
|
||||||
std::optional<std::string> title;
|
std::optional<std::string> title;
|
||||||
std::optional<std::string> length; // as HH:MM:SS
|
std::optional<std::string> length; // as HH:MM:SS
|
||||||
std::optional<std::string> position; // same format
|
std::optional<std::string> position; // same format
|
||||||
@@ -76,6 +77,8 @@ class Mpris : public ALabel {
|
|||||||
std::string player_;
|
std::string player_;
|
||||||
std::vector<std::string> ignored_players_;
|
std::vector<std::string> ignored_players_;
|
||||||
|
|
||||||
|
bool prefer_album_artist_;
|
||||||
|
|
||||||
PlayerctlPlayerManager* manager;
|
PlayerctlPlayerManager* manager;
|
||||||
PlayerctlPlayer* player;
|
PlayerctlPlayer* player;
|
||||||
PlayerctlPlayer* last_active_player_ = nullptr;
|
PlayerctlPlayer* last_active_player_ = nullptr;
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ namespace waybar::modules::SNI {
|
|||||||
|
|
||||||
class Host {
|
class Host {
|
||||||
public:
|
public:
|
||||||
Host(const std::size_t id, const Json::Value&, const Bar&,
|
Host(const std::size_t id, const Json::Value&, const Bar&, const std::vector<std::string>&,
|
||||||
const std::function<void(std::unique_ptr<Item>&)>&,
|
const std::function<void(std::unique_ptr<Item>&)>&,
|
||||||
const std::function<void(std::unique_ptr<Item>&)>&, const std::function<void()>&);
|
const std::function<void(std::unique_ptr<Item>&)>&, const std::function<void()>&);
|
||||||
~Host();
|
~Host();
|
||||||
|
|
||||||
|
void checkIgnoreList(const std::vector<std::string>& ignore_list,
|
||||||
|
const std::function<void(std::unique_ptr<Item>&)>& on_remove);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
|
void busAcquired(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring);
|
||||||
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring,
|
void nameAppeared(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring,
|
||||||
@@ -47,6 +50,7 @@ class Host {
|
|||||||
unsigned retry_count_ = 0;
|
unsigned retry_count_ = 0;
|
||||||
const Json::Value& config_;
|
const Json::Value& config_;
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
|
const std::vector<std::string> ignore_list_;
|
||||||
const std::function<void(std::unique_ptr<Item>&)> on_add_;
|
const std::function<void(std::unique_ptr<Item>&)> on_add_;
|
||||||
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
|
const std::function<void(std::unique_ptr<Item>&)> on_remove_;
|
||||||
const std::function<void()> on_update_;
|
const std::function<void()> on_update_;
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ class Tray : public AModule {
|
|||||||
private:
|
private:
|
||||||
void onAdd(std::unique_ptr<Item>& item);
|
void onAdd(std::unique_ptr<Item>& item);
|
||||||
void onRemove(std::unique_ptr<Item>& item);
|
void onRemove(std::unique_ptr<Item>& item);
|
||||||
|
void checkIgnoreList(std::unique_ptr<Item>* item);
|
||||||
|
std::vector<std::string> parseIgnoreList(const Json::Value& config);
|
||||||
void queueUpdate();
|
void queueUpdate();
|
||||||
|
|
||||||
static inline std::size_t nb_hosts_ = 0;
|
static inline std::size_t nb_hosts_ = 0;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
SNI::Watcher::singleton watcher_;
|
SNI::Watcher::singleton watcher_;
|
||||||
|
std::vector<std::string> ignore_list_;
|
||||||
SNI::Host host_;
|
SNI::Host host_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+36
-9
@@ -6,17 +6,12 @@ waybar - disk module
|
|||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
The *disk* module displays the current disk space used.
|
The *disk* module displays information of multiple disks.
|
||||||
|
|
||||||
# CONFIGURATION
|
# CONFIGURATION
|
||||||
|
|
||||||
Addressed by *disk*
|
Addressed by *disk*
|
||||||
|
|
||||||
*path*: ++
|
|
||||||
typeof: string ++
|
|
||||||
default: "/" ++
|
|
||||||
Any path residing in the filesystem or mountpoint for which the information should be displayed.
|
|
||||||
|
|
||||||
*interval*: ++
|
*interval*: ++
|
||||||
typeof: integer++
|
typeof: integer++
|
||||||
default: 30 ++
|
default: 30 ++
|
||||||
@@ -25,7 +20,7 @@ Addressed by *disk*
|
|||||||
*format*: ++
|
*format*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
default: "{percentage_used}%" ++
|
default: "{percentage_used}%" ++
|
||||||
The format, how information should be displayed.
|
The format, how information for each disk should be displayed.
|
||||||
|
|
||||||
*rotate*: ++
|
*rotate*: ++
|
||||||
typeof: integer ++
|
typeof: integer ++
|
||||||
@@ -75,6 +70,26 @@ Addressed by *disk*
|
|||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when scrolling down on the module.
|
Command to execute when scrolling down on the module.
|
||||||
|
|
||||||
|
*path*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: "/" ++
|
||||||
|
Deprecated path of filesystem or mountpoint to monitor.
|
||||||
|
|
||||||
|
*paths*: ++
|
||||||
|
typeof: array ++
|
||||||
|
default: ["/"] ++
|
||||||
|
Array of paths residing in the filesystem or mountpoint for which the information should be displayed.
|
||||||
|
|
||||||
|
*header*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: "" ++
|
||||||
|
Text to appear before the disk information defined in the format.
|
||||||
|
|
||||||
|
*separator*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: " " ++
|
||||||
|
Separator string between multiple disk information.
|
||||||
|
|
||||||
*smooth-scrolling-threshold*: ++
|
*smooth-scrolling-threshold*: ++
|
||||||
typeof: double ++
|
typeof: double ++
|
||||||
Threshold to be used when scrolling.
|
Threshold to be used when scrolling.
|
||||||
@@ -123,7 +138,7 @@ Addressed by *disk*
|
|||||||
|
|
||||||
*{free}*: Amount of available disk space for normal users. Automatically selects unit based on size remaining.
|
*{free}*: Amount of available disk space for normal users. Automatically selects unit based on size remaining.
|
||||||
|
|
||||||
*{path}*: The path specified in the configuration.
|
*{path}*: The path for each disk specified in the configuration.
|
||||||
|
|
||||||
*{specific_total}*: Total amount of space on the disk, partition, or mountpoint in a specific unit. Defaults to bytes.
|
*{specific_total}*: Total amount of space on the disk, partition, or mountpoint in a specific unit. Defaults to bytes.
|
||||||
|
|
||||||
@@ -143,10 +158,22 @@ Addressed by *disk*
|
|||||||
```
|
```
|
||||||
"disk": {
|
"disk": {
|
||||||
"interval": 30,
|
"interval": 30,
|
||||||
|
"format": "{percentage_free}% free on {path}",
|
||||||
|
"header": "Disks: ",
|
||||||
|
"paths": ["/", "/home"],
|
||||||
|
"separator": " ",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
"disk": {
|
||||||
|
"interval": 30,
|
||||||
|
"paths": ["/"],
|
||||||
"format": "{specific_free:0.2f} GB out of {specific_total:0.2f} GB available. Alternatively {free} out of {total} available",
|
"format": "{specific_free:0.2f} GB out of {specific_total:0.2f} GB available. Alternatively {free} out of {total} available",
|
||||||
"unit": "GB"
|
"unit": "GB"
|
||||||
// 1434.25 GB out of 2000.00 GB available. Alternatively 1.4TiB out of 1.9TiB available.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1434.25 GB out of 2000.00 GB available. Alternatively 1.4TiB out of 1.9TiB available.
|
||||||
```
|
```
|
||||||
|
|
||||||
# STYLE
|
# STYLE
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ Addressed by *dwl/tags*
|
|||||||
typeof: array ++
|
typeof: array ++
|
||||||
The label to display for each tag.
|
The label to display for each tag.
|
||||||
|
|
||||||
|
*hide-vacant*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: false ++
|
||||||
|
If set to true, tags without clients and that are not active will be hidden.
|
||||||
|
|
||||||
*disable-click*: ++
|
*disable-click*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
default: false ++
|
default: false ++
|
||||||
|
|||||||
@@ -36,9 +36,15 @@ auto waybar::modules::Backlight::update() -> void {
|
|||||||
|
|
||||||
if (best->get_powered()) {
|
if (best->get_powered()) {
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
|
|
||||||
const uint8_t percent =
|
const uint8_t percent =
|
||||||
best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
|
best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max());
|
||||||
|
|
||||||
|
const uint8_t percent_exp =
|
||||||
|
best->get_max() == 0
|
||||||
|
? 100
|
||||||
|
: roundf(powf((float)best->get_actual() / best->get_max(), 1.0f / 2.718f) * 100);
|
||||||
|
|
||||||
// Get the state and apply state-specific format if available
|
// Get the state and apply state-specific format if available
|
||||||
auto state = getState(percent);
|
auto state = getState(percent);
|
||||||
std::string current_format = format_;
|
std::string current_format = format_;
|
||||||
@@ -49,8 +55,10 @@ auto waybar::modules::Backlight::update() -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string desc = fmt::format(fmt::runtime(current_format), fmt::arg("percent", percent),
|
std::string desc =
|
||||||
fmt::arg("icon", getIcon(percent)));
|
fmt::format(fmt::runtime(current_format), fmt::arg("percent", percent),
|
||||||
|
fmt::arg("percent_exp", percent_exp), fmt::arg("icon", getIcon(percent)),
|
||||||
|
fmt::arg("icon_exp", getIcon(percent_exp)));
|
||||||
label_.set_markup(desc);
|
label_.set_markup(desc);
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
std::string tooltip_format;
|
std::string tooltip_format;
|
||||||
|
|||||||
+80
-19
@@ -1,15 +1,32 @@
|
|||||||
#include "modules/disk.hpp"
|
#include "modules/disk.hpp"
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
using namespace waybar::util;
|
using namespace waybar::util;
|
||||||
|
|
||||||
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
||||||
: ALabel(config, "disk", id, "{}%", 30), path_("/") {
|
: ALabel(config, "disk", id, "{}%", 30), header_(""), paths_(), separator_(" ") {
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
dp.emit();
|
dp.emit();
|
||||||
thread_.sleep_for(interval_);
|
thread_.sleep_for(interval_);
|
||||||
};
|
};
|
||||||
if (config["path"].isString()) {
|
if (config["header"].isString()) {
|
||||||
path_ = config["path"].asString();
|
header_ = config["header"].asString();
|
||||||
|
}
|
||||||
|
if (config["path"].isString() && !config["paths"].isArray()) {
|
||||||
|
spdlog::warn("Disk: path is deprecated use paths instead!");
|
||||||
|
paths_.push_back(config["path"].asString());
|
||||||
|
}
|
||||||
|
if (config["paths"].isArray()) {
|
||||||
|
for (const auto& path : config["paths"]) {
|
||||||
|
paths_.push_back(path.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!config["path"].isString() && !config["paths"].isArray()) {
|
||||||
|
paths_.emplace_back("/");
|
||||||
|
}
|
||||||
|
if (config["separator"].isString()) {
|
||||||
|
separator_ = config["separator"].asString();
|
||||||
}
|
}
|
||||||
if (config["unit"].isString()) {
|
if (config["unit"].isString()) {
|
||||||
unit_ = config["unit"].asString();
|
unit_ = config["unit"].asString();
|
||||||
@@ -17,6 +34,14 @@ waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Disk::update() -> void {
|
auto waybar::modules::Disk::update() -> void {
|
||||||
|
std::string tooltip_label;
|
||||||
|
std::string label = header_;
|
||||||
|
|
||||||
|
bool had_valid_disk = false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < paths_.size(); ++i) {
|
||||||
|
const auto& path = paths_[i];
|
||||||
|
|
||||||
struct statvfs /* {
|
struct statvfs /* {
|
||||||
unsigned long f_bsize; // filesystem block size
|
unsigned long f_bsize; // filesystem block size
|
||||||
unsigned long f_frsize; // fragment size
|
unsigned long f_frsize; // fragment size
|
||||||
@@ -31,7 +56,8 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
unsigned long f_namemax; // maximum filename length
|
unsigned long f_namemax; // maximum filename length
|
||||||
}; */
|
}; */
|
||||||
stats;
|
stats;
|
||||||
int err = statvfs(path_.c_str(), &stats);
|
|
||||||
|
int err = statvfs(path.c_str(), &stats);
|
||||||
|
|
||||||
/* Conky options
|
/* Conky options
|
||||||
fs_bar - Bar that shows how much space is used
|
fs_bar - Bar that shows how much space is used
|
||||||
@@ -42,8 +68,8 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (err != 0 || stats.f_blocks == 0) {
|
if (err != 0 || stats.f_blocks == 0) {
|
||||||
event_box_.hide();
|
spdlog::warn("Disk: statvfs failed for path '{}' (errno={})", path, errno);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float specific_free, specific_used, specific_total, divisor;
|
float specific_free, specific_used, specific_total, divisor;
|
||||||
@@ -58,23 +84,58 @@ auto waybar::modules::Disk::update() -> void {
|
|||||||
auto total = pow_format(stats.f_blocks * stats.f_frsize, "B", true);
|
auto total = pow_format(stats.f_blocks * stats.f_frsize, "B", true);
|
||||||
auto percentage_used = (stats.f_blocks - stats.f_bfree) * 100 / stats.f_blocks;
|
auto percentage_used = (stats.f_blocks - stats.f_bfree) * 100 / stats.f_blocks;
|
||||||
|
|
||||||
auto format = format_;
|
std::string disk_format = format_;
|
||||||
auto state = getState(percentage_used);
|
auto state = getState(percentage_used);
|
||||||
if (!state.empty() && config_["format-" + state].isString()) {
|
if (!state.empty() && config_["format-" + state].isString()) {
|
||||||
format = config_["format-" + state].asString();
|
disk_format = config_["format-" + state].asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format.empty()) {
|
if (!disk_format.empty()) {
|
||||||
event_box_.hide();
|
if (had_valid_disk) {
|
||||||
} else {
|
label += separator_;
|
||||||
|
}
|
||||||
|
|
||||||
|
label += fmt::format(
|
||||||
|
fmt::runtime(disk_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),
|
||||||
|
fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used),
|
||||||
|
fmt::arg("specific_total", specific_total));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tooltip_format = "{used} used out of {total} on {path} ({percentage_used}%)";
|
||||||
|
if (config_["tooltip-format"].isString()) {
|
||||||
|
tooltip_format = config_["tooltip-format"].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tooltip_format.empty()) {
|
||||||
|
if (had_valid_disk) {
|
||||||
|
tooltip_label += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip_label += fmt::format(
|
||||||
|
fmt::runtime(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),
|
||||||
|
fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used),
|
||||||
|
fmt::arg("specific_total", specific_total));
|
||||||
|
}
|
||||||
|
|
||||||
|
had_valid_disk = true;
|
||||||
|
}
|
||||||
|
if (had_valid_disk) {
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
updateLabelAndTooltip(
|
} else {
|
||||||
format, "{used} used out of {total} on {path} ({percentage_used}%)",
|
event_box_.hide();
|
||||||
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),
|
setLabelMarkup(label);
|
||||||
fmt::arg("path", path_), fmt::arg("specific_free", specific_free),
|
|
||||||
fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total));
|
if (tooltipEnabled() && !tooltip_label.empty()) {
|
||||||
|
setTooltipMarkup(tooltip_label);
|
||||||
}
|
}
|
||||||
// Call parent update
|
// Call parent update
|
||||||
ALabel::update();
|
ALabel::update();
|
||||||
@@ -97,7 +158,7 @@ float waybar::modules::Disk::calc_specific_divisor(const std::string& divisor) {
|
|||||||
return 1000.0 * 1000.0 * 1000.0 * 1000.0;
|
return 1000.0 * 1000.0 * 1000.0 * 1000.0;
|
||||||
} else if (divisor == "TiB") {
|
} else if (divisor == "TiB") {
|
||||||
return 1024.0 * 1024.0 * 1024.0 * 1024.0;
|
return 1024.0 * 1024.0 * 1024.0 * 1024.0;
|
||||||
} else { // default to Bytes if it is anything that we don't recongnise
|
} else { // default to Bytes if it is anything that we don't recognise
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,20 +70,19 @@ static const zdwl_ipc_output_v2_listener output_status_listener_impl{
|
|||||||
|
|
||||||
static void handle_global(void* data, struct wl_registry* registry, uint32_t name,
|
static void handle_global(void* data, struct wl_registry* registry, uint32_t name,
|
||||||
const char* interface, uint32_t version) {
|
const char* interface, uint32_t version) {
|
||||||
|
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
||||||
if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) {
|
|
||||||
auto* self = static_cast<Tags*>(data);
|
auto* self = static_cast<Tags*>(data);
|
||||||
|
|
||||||
if (self->status_manager_) {
|
if (self->status_manager_) {
|
||||||
zdwl_ipc_manager_v2_destroy(self->status_manager_);
|
zdwl_ipc_manager_v2_destroy(self->status_manager_);
|
||||||
self->status_manager_ = nullptr;
|
self->status_manager_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->status_manager_ = static_cast<struct zdwl_ipc_manager_v2*>(
|
self->status_manager_ = static_cast<struct zdwl_ipc_manager_v2*>(
|
||||||
wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
auto* self = static_cast<Tags*>(data);
|
auto* self = static_cast<Tags*>(data);
|
||||||
|
|
||||||
if (self->seat_) {
|
if (self->seat_) {
|
||||||
@@ -93,9 +92,9 @@ if (std::strcmp(interface, wl_seat_interface.name) == 0) {
|
|||||||
|
|
||||||
version = std::min<uint32_t>(version, 1);
|
version = std::min<uint32_t>(version, 1);
|
||||||
|
|
||||||
self->seat_ = static_cast<struct wl_seat*>(
|
self->seat_ =
|
||||||
wl_registry_bind(registry, name, &wl_seat_interface, version));
|
static_cast<struct wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) {
|
static void handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) {
|
||||||
/* Ignore event */
|
/* Ignore event */
|
||||||
@@ -110,7 +109,11 @@ Tags::Tags(const std::string& id, const waybar::Bar& bar, const Json::Value& con
|
|||||||
seat_{nullptr},
|
seat_{nullptr},
|
||||||
bar_(bar),
|
bar_(bar),
|
||||||
box_{bar.orientation, 0},
|
box_{bar.orientation, 0},
|
||||||
|
hide_vacant_(false),
|
||||||
output_status_{nullptr} {
|
output_status_{nullptr} {
|
||||||
|
if (config_["hide-vacant"].asBool()) {
|
||||||
|
hide_vacant_ = config_["hide-vacant"].asBool();
|
||||||
|
}
|
||||||
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);
|
struct wl_registry* registry = wl_display_get_registry(display);
|
||||||
|
|
||||||
@@ -221,6 +224,12 @@ void Tags::handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint
|
|||||||
} else {
|
} else {
|
||||||
button.get_style_context()->remove_class("urgent");
|
button.get_style_context()->remove_class("urgent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hide_vacant_ && !clients && !(state & TAG_ACTIVE)) {
|
||||||
|
button.set_visible(false);
|
||||||
|
} else {
|
||||||
|
button.set_visible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tags::handle_active_output(zdwl_ipc_output_v2* zdwl_output_v2, uint32_t active) {
|
void Tags::handle_active_output(zdwl_ipc_output_v2* zdwl_output_v2, uint32_t active) {
|
||||||
|
|||||||
+13
-5
@@ -1,5 +1,7 @@
|
|||||||
#include "modules/image.hpp"
|
#include "modules/image.hpp"
|
||||||
|
|
||||||
|
#include <config.hpp>
|
||||||
|
|
||||||
waybar::modules::Image::Image(const std::string& id, const Json::Value& config)
|
waybar::modules::Image::Image(const std::string& id, const Json::Value& config)
|
||||||
: AModule(config, "image", id), box_(Gtk::ORIENTATION_HORIZONTAL, 0) {
|
: AModule(config, "image", id), box_(Gtk::ORIENTATION_HORIZONTAL, 0) {
|
||||||
box_.pack_start(image_);
|
box_.pack_start(image_);
|
||||||
@@ -35,6 +37,13 @@ waybar::modules::Image::Image(const std::string& id, const Json::Value& config)
|
|||||||
size_ = 16;
|
size_ = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config_["path"].isString()) {
|
||||||
|
auto result = Config::tryExpandPath(config_["path"].asString(), "");
|
||||||
|
path_ = result.empty() ? "" : result.front();
|
||||||
|
} else {
|
||||||
|
path_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
delayWorker();
|
delayWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,13 +63,12 @@ void waybar::modules::Image::refresh(int sig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Image::update() -> void {
|
auto waybar::modules::Image::update() -> void {
|
||||||
if (config_["path"].isString()) {
|
if (config_["exec"].isString()) {
|
||||||
path_ = config_["path"].asString();
|
|
||||||
} else if (config_["exec"].isString()) {
|
|
||||||
output_ = util::command::exec(config_["exec"].asString(), "");
|
output_ = util::command::exec(config_["exec"].asString(), "");
|
||||||
parseOutputRaw();
|
parseOutputRaw();
|
||||||
} else {
|
// expand path if "~" or "$HOME" is present in original path
|
||||||
path_ = "";
|
auto result = Config::tryExpandPath(path_, "");
|
||||||
|
path_ = result.empty() ? "" : result.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Glib::file_test(path_, Glib::FILE_TEST_EXISTS)) {
|
if (Glib::file_test(path_, Glib::FILE_TEST_EXISTS)) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ Mpris::Mpris(const std::string& id, const Json::Value& config)
|
|||||||
dynamic_separator_(" - "),
|
dynamic_separator_(" - "),
|
||||||
truncate_hours_(true),
|
truncate_hours_(true),
|
||||||
tooltip_len_limits_(false),
|
tooltip_len_limits_(false),
|
||||||
|
prefer_album_artist_(false),
|
||||||
// this character is used in Gnome so it's fine to use it here
|
// this character is used in Gnome so it's fine to use it here
|
||||||
ellipsis_("\u2026"),
|
ellipsis_("\u2026"),
|
||||||
player_("playerctld"),
|
player_("playerctld"),
|
||||||
@@ -68,6 +69,9 @@ Mpris::Mpris(const std::string& id, const Json::Value& config)
|
|||||||
if (config_["enable-tooltip-len-limits"].isBool()) {
|
if (config_["enable-tooltip-len-limits"].isBool()) {
|
||||||
tooltip_len_limits_ = config["enable-tooltip-len-limits"].asBool();
|
tooltip_len_limits_ = config["enable-tooltip-len-limits"].asBool();
|
||||||
}
|
}
|
||||||
|
if (config_["prefer-album-artist"].isBool()) {
|
||||||
|
prefer_album_artist_ = config["prefer-album-artist"].asBool();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config["artist-len"].isUInt()) {
|
if (config["artist-len"].isUInt()) {
|
||||||
@@ -206,6 +210,12 @@ auto Mpris::getIconFromJson(const Json::Value& icons, const std::string& key) ->
|
|||||||
|
|
||||||
auto Mpris::getArtistStr(const PlayerInfo& info, bool truncated) -> std::string {
|
auto Mpris::getArtistStr(const PlayerInfo& info, bool truncated) -> std::string {
|
||||||
auto artist = info.artist.value_or(std::string());
|
auto artist = info.artist.value_or(std::string());
|
||||||
|
if (prefer_album_artist_) {
|
||||||
|
auto album_artist = info.album_artist.value_or(std::string());
|
||||||
|
if (!album_artist.empty()) {
|
||||||
|
artist = album_artist;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (truncated && artist_len_ >= 0) waybar::util::utf8_truncate(artist, ellipsis_, artist_len_);
|
if (truncated && artist_len_ >= 0) waybar::util::utf8_truncate(artist, ellipsis_, artist_len_);
|
||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
@@ -521,6 +531,7 @@ auto Mpris::getPlayerInfo() -> std::optional<PlayerInfo> {
|
|||||||
.status_string = player_status,
|
.status_string = player_status,
|
||||||
.artist = std::nullopt,
|
.artist = std::nullopt,
|
||||||
.album = std::nullopt,
|
.album = std::nullopt,
|
||||||
|
.album_artist = std::nullopt,
|
||||||
.title = std::nullopt,
|
.title = std::nullopt,
|
||||||
.length = std::nullopt,
|
.length = std::nullopt,
|
||||||
};
|
};
|
||||||
@@ -532,6 +543,13 @@ auto Mpris::getPlayerInfo() -> std::optional<PlayerInfo> {
|
|||||||
}
|
}
|
||||||
if (error) goto errorexit;
|
if (error) goto errorexit;
|
||||||
|
|
||||||
|
if (auto* album_artist_ =
|
||||||
|
playerctl_player_print_metadata_prop(player, "xesam:albumArtist", &error)) {
|
||||||
|
spdlog::debug("mpris[{}]: albumArtist = {}", info.name, album_artist_);
|
||||||
|
info.album_artist = album_artist_;
|
||||||
|
g_free(album_artist_);
|
||||||
|
}
|
||||||
|
|
||||||
if (auto* album_ = playerctl_player_get_album(last_active_player_, &error)) {
|
if (auto* album_ = playerctl_player_get_album(last_active_player_, &error)) {
|
||||||
spdlog::debug("mpris[{}]: album = {}", info.name, album_);
|
spdlog::debug("mpris[{}]: album = {}", info.name, album_);
|
||||||
info.album = album_;
|
info.album = album_;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ static const unsigned RETRY_DELAY_MS = 200;
|
|||||||
static const unsigned MAX_RETRIES = 10;
|
static const unsigned MAX_RETRIES = 10;
|
||||||
|
|
||||||
Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
|
Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
|
||||||
|
const std::vector<std::string>& ignore_list,
|
||||||
const std::function<void(std::unique_ptr<Item>&)>& on_add,
|
const std::function<void(std::unique_ptr<Item>&)>& on_add,
|
||||||
const std::function<void(std::unique_ptr<Item>&)>& on_remove,
|
const std::function<void(std::unique_ptr<Item>&)>& on_remove,
|
||||||
const std::function<void()>& on_update)
|
const std::function<void()>& on_update)
|
||||||
@@ -20,6 +21,7 @@ Host::Host(const std::size_t id, const Json::Value& config, const Bar& bar,
|
|||||||
sigc::mem_fun(*this, &Host::busAcquired))),
|
sigc::mem_fun(*this, &Host::busAcquired))),
|
||||||
config_(config),
|
config_(config),
|
||||||
bar_(bar),
|
bar_(bar),
|
||||||
|
ignore_list_(ignore_list),
|
||||||
on_add_(on_add),
|
on_add_(on_add),
|
||||||
on_remove_(on_remove),
|
on_remove_(on_remove),
|
||||||
on_update_(on_update) {}
|
on_update_(on_update) {}
|
||||||
@@ -39,6 +41,42 @@ Host::~Host() {
|
|||||||
g_clear_object(&watcher_);
|
g_clear_object(&watcher_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Host::checkIgnoreList(const std::vector<std::string>& ignore_list,
|
||||||
|
const std::function<void(std::unique_ptr<Item>&)>& on_remove) {
|
||||||
|
spdlog::debug("Host::checkIgnoreList - checking {} items against {} patterns", items_.size(),
|
||||||
|
ignore_list.size());
|
||||||
|
|
||||||
|
for (auto it = items_.begin(); it != items_.end();) {
|
||||||
|
auto& item = *it;
|
||||||
|
spdlog::debug(" Checking item: bus_name='{}', category='{}', icon_name='{}', title='{}'",
|
||||||
|
item->bus_name, item->category, item->icon_name, item->title);
|
||||||
|
|
||||||
|
bool should_remove = false;
|
||||||
|
|
||||||
|
for (const auto& ignored : ignore_list) {
|
||||||
|
if (item->bus_name.find(ignored) != std::string::npos ||
|
||||||
|
item->category.find(ignored) != std::string::npos ||
|
||||||
|
item->icon_name.find(ignored) != std::string::npos ||
|
||||||
|
item->id.find(ignored) != std::string::npos ||
|
||||||
|
item->title.find(ignored) != std::string::npos) {
|
||||||
|
spdlog::info(
|
||||||
|
"Host: Ignoring item bus_name='{}', category='{}', icon_name='{}', title='{}' - "
|
||||||
|
"matched pattern '{}'",
|
||||||
|
item->bus_name, item->category, item->icon_name, item->title, ignored);
|
||||||
|
on_remove(item);
|
||||||
|
should_remove = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_remove) {
|
||||||
|
it = items_.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Host::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib::ustring name) {
|
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::nameAppeared),
|
||||||
@@ -82,7 +120,8 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
|
|||||||
spdlog::error("Host: {}", error->message);
|
spdlog::error("Host: {}", error->message);
|
||||||
g_clear_object(&host->cancellable_);
|
g_clear_object(&host->cancellable_);
|
||||||
if (host->retry_count_ >= MAX_RETRIES) {
|
if (host->retry_count_ >= MAX_RETRIES) {
|
||||||
spdlog::warn("Host: giving up on watcher proxy creation after {} retries", host->retry_count_);
|
spdlog::warn("Host: giving up on watcher proxy creation after {} retries",
|
||||||
|
host->retry_count_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
host->retry_count_ += 1;
|
host->retry_count_ += 1;
|
||||||
@@ -127,7 +166,9 @@ void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
|
|||||||
g_signal_connect(host->watcher_, "item-unregistered", G_CALLBACK(&Host::itemUnregistered), data);
|
g_signal_connect(host->watcher_, "item-unregistered", G_CALLBACK(&Host::itemUnregistered), data);
|
||||||
auto items = sn_watcher_dup_registered_items(host->watcher_);
|
auto items = sn_watcher_dup_registered_items(host->watcher_);
|
||||||
if (items != nullptr) {
|
if (items != nullptr) {
|
||||||
|
spdlog::info("Host: Found {} pre-registered SNI items", g_strv_length(items));
|
||||||
for (uint32_t i = 0; items[i] != nullptr; i += 1) {
|
for (uint32_t i = 0; items[i] != nullptr; i += 1) {
|
||||||
|
spdlog::info("Host: Processing pre-registered item: {}", items[i]);
|
||||||
host->addRegisteredItem(items[i]);
|
host->addRegisteredItem(items[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +177,10 @@ void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
|
|||||||
|
|
||||||
void Host::itemRegistered(SnWatcher* watcher, const gchar* service, gpointer data) {
|
void Host::itemRegistered(SnWatcher* watcher, const gchar* service, gpointer data) {
|
||||||
auto host = static_cast<SNI::Host*>(data);
|
auto host = static_cast<SNI::Host*>(data);
|
||||||
|
spdlog::info("Host::itemRegistered called with service: {}", service);
|
||||||
host->addRegisteredItem(service);
|
host->addRegisteredItem(service);
|
||||||
|
// host->checkIgnoreList(host->ignore_list_, std::bind(&Host::itemUnregistered, host,
|
||||||
|
// std::placeholders::_1, std::placeholders::_2, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::itemUnregistered(SnWatcher* watcher, const gchar* service, gpointer data) {
|
void Host::itemUnregistered(SnWatcher* watcher, const gchar* service, gpointer data) {
|
||||||
@@ -197,17 +241,25 @@ std::tuple<std::string, std::string> Host::getBusNameAndObjectPath(const std::st
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Host::addRegisteredItem(const std::string& service) {
|
void Host::addRegisteredItem(const std::string& service) {
|
||||||
|
// Check service string directly before parsing
|
||||||
|
for (const auto& ignored : ignore_list_) {
|
||||||
|
if (service.find(ignored) != std::string::npos) {
|
||||||
|
spdlog::info("Host: Ignoring service '{}' - matched pattern '{}'", service, ignored);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
std::string bus_name, object_path;
|
std::string bus_name, object_path;
|
||||||
std::tie(bus_name, object_path) = getBusNameAndObjectPath(service);
|
std::tie(bus_name, object_path) = getBusNameAndObjectPath(service);
|
||||||
|
spdlog::debug("SNI item registered: bus_name={}, object_path={}, full_service={}", bus_name,
|
||||||
|
object_path, service);
|
||||||
auto it = std::find_if(items_.begin(), items_.end(), [&bus_name, &object_path](const auto& item) {
|
auto it = std::find_if(items_.begin(), items_.end(), [&bus_name, &object_path](const auto& item) {
|
||||||
return bus_name == item->bus_name && object_path == item->object_path;
|
return bus_name == item->bus_name && object_path == item->object_path;
|
||||||
});
|
});
|
||||||
if (it == items_.end()) {
|
if (it == items_.end()) {
|
||||||
|
spdlog::debug("Adding SNI item: {}", bus_name);
|
||||||
items_.emplace_back(std::make_unique<Item>(
|
items_.emplace_back(std::make_unique<Item>(
|
||||||
bus_name, object_path, config_, bar_,
|
bus_name, object_path, config_, bar_, [this](Item& item) { itemReady(item); },
|
||||||
[this](Item& item) { itemReady(item); },
|
[this](Item& item) { itemInvalidated(item); }, on_update_));
|
||||||
[this](Item& item) { itemInvalidated(item); },
|
|
||||||
on_update_));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,29 @@
|
|||||||
|
|
||||||
namespace waybar::modules::SNI {
|
namespace waybar::modules::SNI {
|
||||||
|
|
||||||
|
std::vector<std::string> Tray::parseIgnoreList(const Json::Value& config) {
|
||||||
|
std::vector<std::string> ignore_list;
|
||||||
|
if (config["ignore-list"].isArray()) {
|
||||||
|
spdlog::info("Tray: Found ignore-list with {} items", config["ignore-list"].size());
|
||||||
|
for (const auto& item : config["ignore-list"]) {
|
||||||
|
if (item.isString()) {
|
||||||
|
ignore_list.push_back(item.asString());
|
||||||
|
spdlog::info("Tray: Adding to ignore list: {}", item.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spdlog::info("Tray: No ignore-list configured");
|
||||||
|
}
|
||||||
|
return ignore_list;
|
||||||
|
}
|
||||||
|
|
||||||
Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: AModule(config, "tray", id),
|
: AModule(config, "tray", id),
|
||||||
box_(bar.orientation, 0),
|
box_(bar.orientation, 0),
|
||||||
watcher_(SNI::Watcher::getInstance()),
|
watcher_(SNI::Watcher::getInstance()),
|
||||||
host_(nb_hosts_, config, bar, std::bind(&Tray::onAdd, this, std::placeholders::_1),
|
ignore_list_(parseIgnoreList(config)),
|
||||||
|
host_(nb_hosts_, config, bar, ignore_list_,
|
||||||
|
std::bind(&Tray::onAdd, this, std::placeholders::_1),
|
||||||
std::bind(&Tray::onRemove, this, std::placeholders::_1),
|
std::bind(&Tray::onRemove, this, std::placeholders::_1),
|
||||||
std::bind(&Tray::queueUpdate, this)) {
|
std::bind(&Tray::queueUpdate, this)) {
|
||||||
box_.set_name("tray");
|
box_.set_name("tray");
|
||||||
@@ -31,14 +49,26 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
|||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tray::checkIgnoreList(std::unique_ptr<Item>* item_ptr) {
|
||||||
|
// Delegate to Host's checkIgnoreList method
|
||||||
|
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
void Tray::queueUpdate() { dp.emit(); }
|
void Tray::queueUpdate() { dp.emit(); }
|
||||||
|
|
||||||
void Tray::onAdd(std::unique_ptr<Item>& item) {
|
void Tray::onAdd(std::unique_ptr<Item>& item) {
|
||||||
|
spdlog::info("Tray::onAdd - item bus_name='{}', category='{}', icon_name='{}', title='{}'",
|
||||||
|
item->bus_name, item->category, item->icon_name, item->title);
|
||||||
|
|
||||||
if (config_["reverse-direction"].isBool() && config_["reverse-direction"].asBool()) {
|
if (config_["reverse-direction"].isBool() && config_["reverse-direction"].asBool()) {
|
||||||
box_.pack_end(item->event_box);
|
box_.pack_end(item->event_box);
|
||||||
} else {
|
} else {
|
||||||
box_.pack_start(item->event_box);
|
box_.pack_start(item->event_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spdlog::debug("Tray::onAdd deferred check - checking ignore list");
|
||||||
|
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
|
||||||
|
|
||||||
item->event_box.signal_show().connect([this] { dp.emit(); });
|
item->event_box.signal_show().connect([this] { dp.emit(); });
|
||||||
item->event_box.signal_hide().connect([this] { dp.emit(); });
|
item->event_box.signal_hide().connect([this] { dp.emit(); });
|
||||||
dp.emit();
|
dp.emit();
|
||||||
@@ -50,6 +80,12 @@ void Tray::onRemove(std::unique_ptr<Item>& item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Tray::update() -> void {
|
auto Tray::update() -> void {
|
||||||
|
// Check if any items should be ignored now that properties have loaded
|
||||||
|
if (!ignore_list_.empty()) {
|
||||||
|
spdlog::debug("Tray::update() - checking ignore list");
|
||||||
|
host_.checkIgnoreList(ignore_list_, std::bind(&Tray::onRemove, this, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Gtk::Widget*> children = box_.get_children();
|
std::vector<Gtk::Widget*> children = box_.get_children();
|
||||||
event_box_.set_visible(std::any_of(children.begin(), children.end(),
|
event_box_.set_visible(std::any_of(children.begin(), children.end(),
|
||||||
[](Gtk::Widget* child) { return child->get_visible(); }));
|
[](Gtk::Widget* child) { return child->get_visible(); }));
|
||||||
|
|||||||
Reference in New Issue
Block a user