Add logind feature, with its 'inhibitor' module
The logind feature adds a new inhibitor module which allows to acquire the inhibitor locks that logind presents. Signed-off-by: Alexis Cellier <kernelserror@gmail.com>
This commit is contained in:
parent
39f42cdd7e
commit
eae65099d0
|
@ -51,6 +51,9 @@
|
||||||
#ifdef HAVE_LIBSNDIO
|
#ifdef HAVE_LIBSNDIO
|
||||||
#include "modules/sndio.hpp"
|
#include "modules/sndio.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_GIO_UNIX
|
||||||
|
#include "modules/inhibitor.hpp"
|
||||||
|
#endif
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/custom.hpp"
|
#include "modules/custom.hpp"
|
||||||
#include "modules/temperature.hpp"
|
#include "modules/temperature.hpp"
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "bar.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
class Inhibitor : public ALabel {
|
||||||
|
public:
|
||||||
|
Inhibitor(const std::string&, const waybar::Bar&, const Json::Value&);
|
||||||
|
~Inhibitor() override;
|
||||||
|
auto update() -> void;
|
||||||
|
auto activated() -> bool;
|
||||||
|
|
||||||
|
private:
|
||||||
|
auto handleToggle(::GdkEventButton* const& e) -> bool;
|
||||||
|
|
||||||
|
const std::unique_ptr<::GDBusConnection, void(*)(::GDBusConnection*)> dbus_;
|
||||||
|
const std::string inhibitors_;
|
||||||
|
int handle_ = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
|
@ -86,7 +86,7 @@ wayland_cursor = dependency('wayland-cursor')
|
||||||
wayland_protos = dependency('wayland-protocols')
|
wayland_protos = dependency('wayland-protocols')
|
||||||
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
|
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
|
||||||
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
|
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
|
||||||
giounix = dependency('gio-unix-2.0', required: get_option('dbusmenu-gtk'))
|
giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled()))
|
||||||
jsoncpp = dependency('jsoncpp')
|
jsoncpp = dependency('jsoncpp')
|
||||||
sigcpp = dependency('sigc++-2.0')
|
sigcpp = dependency('sigc++-2.0')
|
||||||
libepoll = dependency('epoll-shim', required: false)
|
libepoll = dependency('epoll-shim', required: false)
|
||||||
|
@ -242,6 +242,11 @@ if libsndio.found()
|
||||||
src_files += 'src/modules/sndio.cpp'
|
src_files += 'src/modules/sndio.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if (giounix.found() and not get_option('logind').disabled())
|
||||||
|
add_project_arguments('-DHAVE_GIO_UNIX', language: 'cpp')
|
||||||
|
src_files += 'src/modules/inhibitor.cpp'
|
||||||
|
endif
|
||||||
|
|
||||||
if get_option('rfkill').enabled()
|
if get_option('rfkill').enabled()
|
||||||
if is_linux
|
if is_linux
|
||||||
add_project_arguments('-DWANT_RFKILL', language: 'cpp')
|
add_project_arguments('-DWANT_RFKILL', language: 'cpp')
|
||||||
|
|
|
@ -10,5 +10,6 @@ option('mpd', type: 'feature', value: 'auto', description: 'Enable support for t
|
||||||
option('gtk-layer-shell', type: 'feature', value: 'auto', description: 'Use gtk-layer-shell library for popups support')
|
option('gtk-layer-shell', type: 'feature', value: 'auto', description: 'Use gtk-layer-shell library for popups support')
|
||||||
option('rfkill', type: 'feature', value: 'auto', description: 'Enable support for RFKILL')
|
option('rfkill', type: 'feature', value: 'auto', description: 'Enable support for RFKILL')
|
||||||
option('sndio', type: 'feature', value: 'auto', description: 'Enable support for sndio')
|
option('sndio', type: 'feature', value: 'auto', description: 'Enable support for sndio')
|
||||||
|
option('logind', type: 'feature', value: 'auto', description: 'Enable support for logind')
|
||||||
option('tests', type: 'feature', value: 'auto', description: 'Enable tests')
|
option('tests', type: 'feature', value: 'auto', description: 'Enable tests')
|
||||||
option('experimental', type : 'boolean', value : false, description: 'Enable experimental features')
|
option('experimental', type : 'boolean', value : false, description: 'Enable experimental features')
|
||||||
|
|
|
@ -94,6 +94,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
if (ref == "sndio") {
|
if (ref == "sndio") {
|
||||||
return new waybar::modules::Sndio(id, config_[name]);
|
return new waybar::modules::Sndio(id, config_[name]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GIO_UNIX
|
||||||
|
if (ref == "inhibitor") {
|
||||||
|
return new waybar::modules::Inhibitor(id, bar_, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ref == "temperature") {
|
if (ref == "temperature") {
|
||||||
return new waybar::modules::Temperature(id, config_[name]);
|
return new waybar::modules::Temperature(id, config_[name]);
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
#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
|
Loading…
Reference in New Issue