diff --git a/CHANGELOG.md b/CHANGELOG.md index 18ec7d7d..d8542da9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- When the `-r` flag is provided, and RandR reports zero connected active screens, Polybar will not restart. This fixes Polybar dying on some laptops when the lid is closed. [`#3078`](https://github.com/polybar/polybar/pull/3078). + ## [3.7.1] - 2023-11-27 ### Build - Fixed missing header when using `libc++` in clang 15 and below diff --git a/include/components/screen.hpp b/include/components/screen.hpp index 95e41e08..3dd67333 100644 --- a/include/components/screen.hpp +++ b/include/components/screen.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "common.hpp" #include "components/types.hpp" #include "events/signal_emitter.hpp" @@ -49,7 +51,7 @@ class screen : public xpp::event::sink have_monitors_changed() const; }; POLYBAR_NS_END diff --git a/src/components/screen.cpp b/src/components/screen.cpp index ac39f6db..c2699d60 100644 --- a/src/components/screen.cpp +++ b/src/components/screen.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "components/config.hpp" #include "components/logger.hpp" @@ -101,13 +102,16 @@ void screen::handle(const evt::randr_screen_change_notify& evt) { m_connection.reset_screen(); auto screen = m_connection.screen(); - auto changed = false; - // We need to reload if the screen size changed as well + auto [changed, num_monitors] = have_monitors_changed(); + if (num_monitors == 0) { + m_log.notice("randr_screen_change_notify got 0 connected screens, ignoring event"); + return; + } + + // We need to reload if the screen size changed as well, not just if screens were added/removed. if (screen->width_in_pixels != m_size.w || screen->height_in_pixels != m_size.h) { changed = true; - } else { - changed = have_monitors_changed(); } if (changed) { @@ -120,13 +124,14 @@ void screen::handle(const evt::randr_screen_change_notify& evt) { /** * Checks if the stored monitor list is different from a newly fetched one * - * Fetches the monitor list and compares it with the one stored + * Fetches the monitor list and compares it with the one stored. Returns + * true if the list of monitors has changed. Also returns the number of monitors. */ -bool screen::have_monitors_changed() const { +std::pair screen::have_monitors_changed() const { auto monitors = randr_util::get_monitors(m_connection, true, false); if (monitors.size() != m_monitors.size()) { - return true; + return std::make_pair(true, monitors.size()); } for (auto m : m_monitors) { @@ -139,11 +144,11 @@ bool screen::have_monitors_changed() const { * the same size */ if (it == monitors.end()) { - return true; + return std::make_pair(true, monitors.size()); } } - return false; + return std::make_pair(false, monitors.size()); } POLYBAR_NS_END