fix: don't restart if zero active screens are reported

On laptops and similar devices, RandR sometimes returns zero active
screens, for example when closing a laptop's lid before it suspends.

Don't restart in that case because the new polybar instance will see
zero screens and quit. Instead, just ignore those kind of events.
This commit is contained in:
Gregor Best 2024-01-17 19:44:33 +01:00
parent b4d8be590b
commit dbec7746b1
3 changed files with 20 additions and 10 deletions

View File

@ -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

View File

@ -1,5 +1,7 @@
#pragma once
#include <utility>
#include "common.hpp"
#include "components/types.hpp"
#include "events/signal_emitter.hpp"
@ -49,7 +51,7 @@ class screen : public xpp::event::sink<evt::map_notify, evt::randr_screen_change
*/
uint32_t m_root_mask{0};
bool have_monitors_changed() const;
std::pair<bool, int> have_monitors_changed() const;
};
POLYBAR_NS_END

View File

@ -3,6 +3,7 @@
#include <algorithm>
#include <csignal>
#include <thread>
#include <utility>
#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<bool, int> 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