Files
Waybar/src/modules/inhibitor.cpp
Simon Plakolb 2b735f44bc modules: Set tooltip on button
Mouse-over tooltips set on the label only appear once the mouse hovers
over exactly the label. Other apps (e.g. firefox) show the tooltip once
the pointer hovers the button. Not solely its label. With this commit we
get the same behaviour.
2022-10-12 10:25:30 +02:00

149 lines
4.3 KiB
C++

#include "modules/inhibitor.hpp"
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <spdlog/spdlog.h>
namespace {
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);
if (error) {
spdlog::error("g_bus_get_sync() failed: {}", error->message);
g_error_free(error);
connection = nullptr;
}
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);
}
};
return DBus{connection, destructor};
}
auto getLocks(const DBus& bus, const std::string& inhibitors) -> int {
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);
if (error) {
spdlog::error("g_dbus_connection_call_with_unix_fd_list_sync() failed: {}", error->message);
g_error_free(error);
handle = -1;
} else {
gint index;
g_variant_get(reply, "(h)", &index);
g_variant_unref(reply);
handle = g_unix_fd_list_get(fd_list, index, nullptr);
g_object_unref(fd_list);
}
return handle;
}
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"};
if (std::find(inhibitors.begin(), inhibitors.end(), inhibitor) == inhibitors.end()) {
throw std::runtime_error("invalid logind inhibitor " + inhibitor);
}
return inhibitor;
}
auto getInhibitors(const Json::Value& config) -> std::string {
std::string inhibitors = "idle";
if (config["what"].empty()) {
return inhibitors;
}
if (config["what"].isString()) {
return checkInhibitor(config["what"].asString());
}
if (config["what"].isArray()) {
inhibitors = checkInhibitor(config["what"][0].asString());
for (decltype(config["what"].size()) i = 1; i < config["what"].size(); ++i) {
inhibitors += ":" + checkInhibitor(config["what"][i].asString());
}
return inhibitors;
}
return inhibitors;
}
} // namespace
namespace waybar::modules {
Inhibitor::Inhibitor(const std::string& id, const Bar& bar, const Json::Value& config)
: AButton(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));
dp.emit();
}
Inhibitor::~Inhibitor() {
if (handle_ != -1) {
::close(handle_);
}
}
auto Inhibitor::activated() -> bool { return handle_ != -1; }
auto Inhibitor::update() -> void {
std::string status_text = activated() ? "activated" : "deactivated";
button_.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))));
button_.get_style_context()->add_class(status_text);
if (tooltipEnabled()) {
button_.set_tooltip_text(status_text);
}
return AButton::update();
}
auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool {
if (e->button == 1) {
if (activated()) {
::close(handle_);
handle_ = -1;
} else {
handle_ = ::getLocks(dbus_, inhibitors_);
if (handle_ == -1) {
spdlog::error("cannot get inhibitor locks");
}
}
}
return AButton::handleToggle(e);
}
} // namespace waybar::modules