From abfc6b7f91e5ad31604356170cd574cd3b37dad2 Mon Sep 17 00:00:00 2001 From: patrick96 Date: Wed, 23 Mar 2022 14:07:51 +0100 Subject: [PATCH] fix(xworkspaces): Crash if number of desktops too small Fixes #2660 --- src/modules/xworkspaces.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/modules/xworkspaces.cpp b/src/modules/xworkspaces.cpp index 1e4dd50a..dd64c44c 100644 --- a/src/modules/xworkspaces.cpp +++ b/src/modules/xworkspaces.cpp @@ -171,7 +171,7 @@ namespace modules { void xworkspaces_module::rebuild_urgent_hints() { m_urgent_desktops.assign(m_desktop_names.size(), false); for (auto&& client : ewmh_util::get_client_list()) { - auto desk = ewmh_util::get_desktop_from_window(client); + uint32_t desk = ewmh_util::get_desktop_from_window(client); /* * EWMH allows for 0xFFFFFFFF to be returned here, which means the window * should appear on all desktops. @@ -198,8 +198,8 @@ namespace modules { * * For WMs that don't support that hint, we store an empty vector * - * If the length of the vector is less than _NET_NUMBER_OF_DESKTOPS - * all desktops which aren't explicitly assigned a postion will be + * The vector will be padded/reduced to _NET_NUMBER_OF_DESKTOPS. + * All desktops which aren't explicitly assigned a postion will be * assigned (0, 0) * * We use this to map workspaces to viewports, desktop i is at position @@ -207,16 +207,31 @@ namespace modules { */ vector ws_positions = ewmh_util::get_desktop_viewports(); + auto num_desktops = m_desktop_names.size(); + /* * Not all desktops were assigned a viewport, add (0, 0) for all missing * desktops. */ - if (ws_positions.size() < m_desktop_names.size()) { - auto num_insert = m_desktop_names.size() - ws_positions.size(); - ws_positions.reserve(num_insert); + if (ws_positions.size() < num_desktops) { + auto num_insert = num_desktops - ws_positions.size(); + ws_positions.reserve(num_desktops); std::fill_n(std::back_inserter(ws_positions), num_insert, position{0, 0}); } + /* + * If there are too many workspace positions, trim to fit the number of desktops. + */ + if (ws_positions.size() > num_desktops) { + ws_positions.erase(ws_positions.begin() + num_desktops, ws_positions.end()); + } + + /* + * There must be as many workspace positions as desktops because the indices + * into ws_positions are also used to index into m_desktop_names. + */ + assert(ws_positions.size() == num_desktops); + /* * The list of viewports is the set of unique positions in ws_positions * Using a set automatically removes duplicates. @@ -252,6 +267,10 @@ namespace modules { return label; }(); + /* + * Search for all desktops on this viewport and store them in the + * desktop list of the viewport. + */ for (size_t i = 0; i < ws_positions.size(); i++) { auto&& ws_pos = ws_positions[i]; if (ws_pos == viewport_pos) {