feat(modules): pause background threads when display is asleep
Currently, modules polling hardware nodes continuously wake up kernel drivers even when the monitor is asleep (e.g., DPMS off), flooding dmesg. - Adds 'disable-on-sleep' config flag - Hooks GTK window map/unmap signals to track DPMS state - Propagates suspend/resume calls to AModule worker threads
This commit is contained in:
@@ -25,6 +25,10 @@ class AModule : public IModule {
|
|||||||
|
|
||||||
bool expandEnabled() const;
|
bool expandEnabled() const;
|
||||||
|
|
||||||
|
virtual void suspend() {};
|
||||||
|
virtual void resume() {};
|
||||||
|
bool shouldSuspend() const { return disable_on_sleep_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Don't need to make an object directly
|
// Don't need to make an object directly
|
||||||
// Derived classes are able to use it
|
// Derived classes are able to use it
|
||||||
@@ -48,6 +52,8 @@ class AModule : public IModule {
|
|||||||
virtual bool handleMouseLeave(GdkEventCrossing* const& ev);
|
virtual bool handleMouseLeave(GdkEventCrossing* const& ev);
|
||||||
virtual bool handleScroll(GdkEventScroll*);
|
virtual bool handleScroll(GdkEventScroll*);
|
||||||
virtual bool handleRelease(GdkEventButton* const& ev);
|
virtual bool handleRelease(GdkEventButton* const& ev);
|
||||||
|
|
||||||
|
bool disable_on_sleep_{false};
|
||||||
GObject* menu_ = nullptr;
|
GObject* menu_ = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ class Bar : public sigc::trackable {
|
|||||||
util::KillSignalAction getOnSigusr1Action();
|
util::KillSignalAction getOnSigusr1Action();
|
||||||
util::KillSignalAction getOnSigusr2Action();
|
util::KillSignalAction getOnSigusr2Action();
|
||||||
|
|
||||||
|
void toggleSuspend(bool suspend);
|
||||||
|
|
||||||
struct waybar_output* output;
|
struct waybar_output* output;
|
||||||
Json::Value config;
|
Json::Value config;
|
||||||
struct wl_surface* surface;
|
struct wl_surface* surface;
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class Temperature : public ALabel {
|
|||||||
Temperature(const std::string&, const Json::Value&);
|
Temperature(const std::string&, const Json::Value&);
|
||||||
virtual ~Temperature() = default;
|
virtual ~Temperature() = default;
|
||||||
auto update() -> void override;
|
auto update() -> void override;
|
||||||
|
void suspend() override;
|
||||||
|
void resume() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float getTemperature();
|
float getTemperature();
|
||||||
|
|||||||
@@ -79,6 +79,12 @@ class SleeperThread {
|
|||||||
auto sleep_for(std::chrono::system_clock::duration dur) {
|
auto sleep_for(std::chrono::system_clock::duration dur) {
|
||||||
std::unique_lock lk(mutex_);
|
std::unique_lock lk(mutex_);
|
||||||
CancellationGuard cancel_lock;
|
CancellationGuard cancel_lock;
|
||||||
|
|
||||||
|
condvar_.wait(lk, [this] {
|
||||||
|
return !is_paused_ || signal_.load(std::memory_order_relaxed) ||
|
||||||
|
!do_run_.load(std::memory_order_relaxed);
|
||||||
|
});
|
||||||
|
|
||||||
constexpr auto max_time_point = std::chrono::steady_clock::time_point::max();
|
constexpr auto max_time_point = std::chrono::steady_clock::time_point::max();
|
||||||
auto wait_end = max_time_point;
|
auto wait_end = max_time_point;
|
||||||
auto now = std::chrono::steady_clock::now();
|
auto now = std::chrono::steady_clock::now();
|
||||||
@@ -95,6 +101,12 @@ class SleeperThread {
|
|||||||
time_point) {
|
time_point) {
|
||||||
std::unique_lock lk(mutex_);
|
std::unique_lock lk(mutex_);
|
||||||
CancellationGuard cancel_lock;
|
CancellationGuard cancel_lock;
|
||||||
|
|
||||||
|
condvar_.wait(lk, [this] {
|
||||||
|
return !is_paused_ || signal_.load(std::memory_order_relaxed) ||
|
||||||
|
!do_run_.load(std::memory_order_relaxed);
|
||||||
|
});
|
||||||
|
|
||||||
return condvar_.wait_until(lk, time_point, [this] {
|
return condvar_.wait_until(lk, time_point, [this] {
|
||||||
return signal_.load(std::memory_order_relaxed) || !do_run_.load(std::memory_order_relaxed);
|
return signal_.load(std::memory_order_relaxed) || !do_run_.load(std::memory_order_relaxed);
|
||||||
});
|
});
|
||||||
@@ -122,6 +134,17 @@ class SleeperThread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pause() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
is_paused_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resume() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
is_paused_ = false;
|
||||||
|
condvar_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
~SleeperThread() {
|
~SleeperThread() {
|
||||||
connection_.disconnect();
|
connection_.disconnect();
|
||||||
stop();
|
stop();
|
||||||
@@ -137,6 +160,7 @@ class SleeperThread {
|
|||||||
std::atomic<bool> do_run_ = true;
|
std::atomic<bool> do_run_ = true;
|
||||||
std::atomic<bool> signal_ = false;
|
std::atomic<bool> signal_ = false;
|
||||||
sigc::connection connection_;
|
sigc::connection connection_;
|
||||||
|
bool is_paused_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::util
|
} // namespace waybar::util
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ AModule::AModule(const Json::Value& config, const std::string& name, const std::
|
|||||||
// Configure module action Map
|
// Configure module action Map
|
||||||
const Json::Value actions{config_["actions"]};
|
const Json::Value actions{config_["actions"]};
|
||||||
|
|
||||||
|
disable_on_sleep_ =
|
||||||
|
config_["disable-on-sleep"].isBool() ? config_["disable-on-sleep"].asBool() : false;
|
||||||
|
|
||||||
for (Json::Value::const_iterator it = actions.begin(); it != actions.end(); ++it) {
|
for (Json::Value::const_iterator it = actions.begin(); it != actions.end(); ++it) {
|
||||||
if (it.key().isString() && it->isString())
|
if (it.key().isString() && it->isString())
|
||||||
if (!eventActionMap_.contains(it.key().asString())) {
|
if (!eventActionMap_.contains(it.key().asString())) {
|
||||||
|
|||||||
+31
-2
@@ -263,6 +263,16 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
|
|||||||
|
|
||||||
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
|
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
|
||||||
|
|
||||||
|
window.signal_unmap().connect([this]() {
|
||||||
|
spdlog::debug("Output {} unmapped (DPMS off), suspending modules", output->name);
|
||||||
|
toggleSuspend(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.signal_map().connect([this]() {
|
||||||
|
spdlog::debug("Output {} mapped (DPMS on), resuming modules", output->name);
|
||||||
|
toggleSuspend(false);
|
||||||
|
});
|
||||||
|
|
||||||
#if HAVE_SWAY
|
#if HAVE_SWAY
|
||||||
if (auto ipc = config["ipc"]; ipc.isBool() && ipc.asBool()) {
|
if (auto ipc = config["ipc"]; ipc.isBool() && ipc.asBool()) {
|
||||||
bar_id = Client::inst()->bar_id;
|
bar_id = Client::inst()->bar_id;
|
||||||
@@ -545,8 +555,8 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
|
|||||||
if (group_config["modules"].isNull()) {
|
if (group_config["modules"].isNull()) {
|
||||||
spdlog::warn("Group definition '{}' has not been found, group will be hidden", ref);
|
spdlog::warn("Group definition '{}' has not been found, group will be hidden", ref);
|
||||||
}
|
}
|
||||||
auto group_module = std::make_unique<waybar::Group>(
|
auto group_module =
|
||||||
id_name, class_name, group_config, vertical);
|
std::make_unique<waybar::Group>(id_name, class_name, group_config, vertical);
|
||||||
|
|
||||||
getModules(factory, ref, group_module.get());
|
getModules(factory, ref, group_module.get());
|
||||||
module = group_module.release();
|
module = group_module.release();
|
||||||
@@ -696,3 +706,22 @@ void waybar::Bar::configureGlobalOffset(int width, int height) {
|
|||||||
void waybar::Bar::onOutputGeometryChanged() {
|
void waybar::Bar::onOutputGeometryChanged() {
|
||||||
configureGlobalOffset(window.get_width(), window.get_height());
|
configureGlobalOffset(window.get_width(), window.get_height());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::Bar::toggleSuspend(bool suspend) {
|
||||||
|
auto process_modules = [suspend](Gtk::Box& module_box) {
|
||||||
|
for (auto* widget : module_box.get_children()) {
|
||||||
|
auto* module = dynamic_cast<waybar::AModule*>(widget);
|
||||||
|
if (module && module->shouldSuspend()) {
|
||||||
|
if (suspend) {
|
||||||
|
module->suspend();
|
||||||
|
} else {
|
||||||
|
module->resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
process_modules(left_);
|
||||||
|
process_modules(center_);
|
||||||
|
process_modules(right_);
|
||||||
|
}
|
||||||
|
|||||||
@@ -155,3 +155,7 @@ bool waybar::modules::Temperature::isCritical(uint16_t temperature_c) {
|
|||||||
return config_["critical-threshold"].isInt() &&
|
return config_["critical-threshold"].isInt() &&
|
||||||
temperature_c >= config_["critical-threshold"].asInt();
|
temperature_c >= config_["critical-threshold"].asInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waybar::modules::Temperature::suspend() { thread_.pause(); }
|
||||||
|
|
||||||
|
void waybar::modules::Temperature::resume() { thread_.resume(); }
|
||||||
|
|||||||
Reference in New Issue
Block a user