mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-11-04 09:42:42 +01:00 
			
		
		
		
	Merge pull request #1341 from fhost/fhost/logind
Add logind feature, with its 'inhibitor' module
This commit is contained in:
		@@ -51,6 +51,9 @@
 | 
			
		||||
#ifdef HAVE_LIBSNDIO
 | 
			
		||||
#include "modules/sndio.hpp"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HAVE_GIO_UNIX
 | 
			
		||||
#include "modules/inhibitor.hpp"
 | 
			
		||||
#endif
 | 
			
		||||
#include "bar.hpp"
 | 
			
		||||
#include "modules/custom.hpp"
 | 
			
		||||
#include "modules/temperature.hpp"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								include/modules/inhibitor.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/modules/inhibitor.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -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')
 | 
			
		||||
gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0'])
 | 
			
		||||
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')
 | 
			
		||||
sigcpp = dependency('sigc++-2.0')
 | 
			
		||||
libepoll = dependency('epoll-shim', required: false)
 | 
			
		||||
@@ -242,6 +242,11 @@ if libsndio.found()
 | 
			
		||||
    src_files += 'src/modules/sndio.cpp'
 | 
			
		||||
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 is_linux
 | 
			
		||||
        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('rfkill', type: 'feature', value: 'auto', description: 'Enable support for RFKILL')
 | 
			
		||||
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('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") {
 | 
			
		||||
      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
 | 
			
		||||
    if (ref == "temperature") {
 | 
			
		||||
      return new waybar::modules::Temperature(id, config_[name]);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										175
									
								
								src/modules/inhibitor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								src/modules/inhibitor.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
		Reference in New Issue
	
	Block a user