mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
176 lines
4.2 KiB
C++
176 lines
4.2 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 waybar::modules {
|
||
|
|
||
|
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));
|
||
|
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";
|
||
|
|
||
|
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()) {
|
||
|
label_.set_tooltip_text(status_text);
|
||
|
}
|
||
|
|
||
|
return ALabel::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 ALabel::handleToggle(e);
|
||
|
}
|
||
|
|
||
|
} // waybar::modules
|