fix(monitor): Reload when any monitor changes
Before it would only reload if the size changed and even that was reliable since the method relied on the order of the monitor list. Now if the monitor list differs in any way (pos, dimension, primary, output, name) a reload is issued
This commit is contained in:
parent
18fc64f881
commit
ecbe77bbda
@ -47,6 +47,8 @@ class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
|
|||||||
vector<monitor_t> m_monitors;
|
vector<monitor_t> m_monitors;
|
||||||
struct size m_size {0U, 0U};
|
struct size m_size {0U, 0U};
|
||||||
bool m_sigraised{false};
|
bool m_sigraised{false};
|
||||||
|
|
||||||
|
bool have_monitors_changed() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -42,6 +42,8 @@ struct randr_output {
|
|||||||
bool match(const position& p) const;
|
bool match(const position& p) const;
|
||||||
|
|
||||||
bool contains(const randr_output& output) const;
|
bool contains(const randr_output& output) const;
|
||||||
|
|
||||||
|
bool equals(const randr_output& output) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using monitor_t = shared_ptr<randr_output>;
|
using monitor_t = shared_ptr<randr_output>;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <algorithm>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "components/config.hpp"
|
#include "components/config.hpp"
|
||||||
@ -33,7 +34,7 @@ screen::screen(connection& conn, signal_emitter& emitter, const logger& logger,
|
|||||||
, m_log(logger)
|
, m_log(logger)
|
||||||
, m_conf(conf)
|
, m_conf(conf)
|
||||||
, m_root(conn.root())
|
, m_root(conn.root())
|
||||||
, m_monitors(randr_util::get_monitors(m_connection, m_root, true))
|
, m_monitors(randr_util::get_monitors(m_connection, m_root, true, false))
|
||||||
, m_size({conn.screen()->width_in_pixels, conn.screen()->height_in_pixels}) {
|
, m_size({conn.screen()->width_in_pixels, conn.screen()->height_in_pixels}) {
|
||||||
// Check if the reloading has been disabled by the user
|
// Check if the reloading has been disabled by the user
|
||||||
if (!m_conf.get("settings", "screenchange-reload", false)) {
|
if (!m_conf.get("settings", "screenchange-reload", false)) {
|
||||||
@ -88,7 +89,7 @@ screen::~screen() {
|
|||||||
/**
|
/**
|
||||||
* Handle XCB_RANDR_SCREEN_CHANGE_NOTIFY events
|
* Handle XCB_RANDR_SCREEN_CHANGE_NOTIFY events
|
||||||
*
|
*
|
||||||
* If the screen dimensions have changed we raise USR1 to trigger a reload
|
* If any of the monitors have changed we raise USR1 to trigger a reload
|
||||||
*/
|
*/
|
||||||
void screen::handle(const evt::randr_screen_change_notify& evt) {
|
void screen::handle(const evt::randr_screen_change_notify& evt) {
|
||||||
if (m_sigraised || evt->request_window != m_proxy) {
|
if (m_sigraised || evt->request_window != m_proxy) {
|
||||||
@ -98,24 +99,49 @@ void screen::handle(const evt::randr_screen_change_notify& evt) {
|
|||||||
auto screen = m_connection.screen(true);
|
auto screen = m_connection.screen(true);
|
||||||
auto changed = false;
|
auto changed = false;
|
||||||
|
|
||||||
|
// We need to reload if the screen size changed as well
|
||||||
if (screen->width_in_pixels != m_size.w || screen->height_in_pixels != m_size.h) {
|
if (screen->width_in_pixels != m_size.w || screen->height_in_pixels != m_size.h) {
|
||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
auto monitors = randr_util::get_monitors(m_connection, m_root, true, false);
|
changed = have_monitors_changed();
|
||||||
for (size_t n = 0; n < monitors.size(); n++) {
|
|
||||||
if (n < m_monitors.size() && monitors[n]->output != m_monitors[n]->output) {
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!changed) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
m_log.warn("randr_screen_change_notify (%ux%u)... reloading", evt->width, evt->height);
|
m_log.warn("randr_screen_change_notify (%ux%u)... reloading", evt->width, evt->height);
|
||||||
m_sig.emit(exit_reload{});
|
m_sig.emit(exit_reload{});
|
||||||
m_sigraised = true;
|
m_sigraised = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the stored monitor list is different from a newly fetched one
|
||||||
|
*
|
||||||
|
* Fetches the monitor list and compares it with the one stored
|
||||||
|
*/
|
||||||
|
bool screen::have_monitors_changed() const {
|
||||||
|
auto monitors = randr_util::get_monitors(m_connection, m_root, true, false);
|
||||||
|
|
||||||
|
if(monitors.size() != m_monitors.size()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto m : m_monitors) {
|
||||||
|
auto it = std::find_if(monitors.begin(), monitors.end(),
|
||||||
|
[m] (auto& monitor) -> bool {
|
||||||
|
return m->equals(*monitor);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Every monitor in the stored list should also exist in the newly fetched
|
||||||
|
* list. If this holds then the two lists are equivalent since they have
|
||||||
|
* the same size
|
||||||
|
*/
|
||||||
|
if(it == monitors.end()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -42,6 +42,16 @@ bool randr_output::contains(const randr_output& inner) const {
|
|||||||
&& inner.y >= y && inner.y + inner.h <= y + h;
|
&& inner.y >= y && inner.y + inner.h <= y + h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given output is the same as this
|
||||||
|
*
|
||||||
|
* Looks at xcb_randr_output_t, position, dimension, name and 'primary'
|
||||||
|
*/
|
||||||
|
bool randr_output::equals(const randr_output& o) const {
|
||||||
|
return o.output == output && o.x == x && o.y == y && o.w == w && o.h == h &&
|
||||||
|
o.primary == primary && o.name == name;
|
||||||
|
}
|
||||||
|
|
||||||
namespace randr_util {
|
namespace randr_util {
|
||||||
/**
|
/**
|
||||||
* XRandR version
|
* XRandR version
|
||||||
|
Loading…
Reference in New Issue
Block a user