diff --git a/include/components/screen.hpp b/include/components/screen.hpp index 8cb4af97..ae51de2c 100644 --- a/include/components/screen.hpp +++ b/include/components/screen.hpp @@ -36,6 +36,7 @@ class screen : public xpp::event::sink { xcb_window_t m_root; xcb_window_t m_proxy{XCB_NONE}; + vector m_monitors; struct size m_size{0U, 0U}; bool m_sigraised{false}; }; diff --git a/include/x11/connection.hpp b/include/x11/connection.hpp index 1f28a7b7..6e99f202 100644 --- a/include/x11/connection.hpp +++ b/include/x11/connection.hpp @@ -59,7 +59,7 @@ class connection : public xpp_connection { string id(xcb_window_t w) const; - xcb_screen_t* screen(); + xcb_screen_t* screen(bool realloc = false); void ensure_event_mask(xcb_window_t win, uint32_t event); void clear_event_mask(xcb_window_t win); diff --git a/src/components/screen.cpp b/src/components/screen.cpp index 33852fd2..53c36cce 100644 --- a/src/components/screen.cpp +++ b/src/components/screen.cpp @@ -28,6 +28,7 @@ screen::screen(connection& conn, const logger& logger, const config& conf) , m_log(logger) , m_conf(conf) , m_root(conn.root()) + , m_monitors(randr_util::get_monitors(m_connection, m_root, true)) , m_size({conn.screen()->width_in_pixels, conn.screen()->height_in_pixels}) { assert(g_signals::event::enqueue != nullptr); @@ -80,9 +81,29 @@ screen::~screen() { * If the screen dimensions have changed we raise USR1 to trigger a reload */ 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) { + return; + } + + auto screen = m_connection.screen(true); + auto changed = false; + + if (screen->width_in_pixels != m_size.w || screen->height_in_pixels != m_size.h) { + changed = true; + } else { + auto monitors = randr_util::get_monitors(m_connection, m_root, true); + + 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) { m_log.warn("randr_screen_change_notify (%ux%u)... reloading", evt->width, evt->height); m_sigraised = true; + quit_event quit{}; quit.reload = true; g_signals::event::enqueue(reinterpret_cast(quit)); diff --git a/src/x11/connection.cpp b/src/x11/connection.cpp index f6d042a8..7003d191 100644 --- a/src/x11/connection.cpp +++ b/src/x11/connection.cpp @@ -102,8 +102,8 @@ string connection::id(xcb_window_t w) const { /** * Get pointer to the default xcb screen */ -xcb_screen_t* connection::screen() { - if (m_screen == nullptr) { +xcb_screen_t* connection::screen(bool realloc) { + if (m_screen == nullptr || realloc) { m_screen = screen_of_display(default_screen()); } return m_screen;